单链表——“数据结构与算法”

这篇具有很好参考价值的文章主要介绍了单链表——“数据结构与算法”。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

各位CSDN的uu们你们好呀,今天,小雅兰的内容终于是我们心心念念的单链表啦,这一块呢,是一个很重要的部分,也是一个对目前的我来说,比较困难的部分,下面,就让我们进入单链表的世界吧


之前小雅兰写过顺序表的内容:

顺序表(更新版)——“数据结构与算法”_认真学习的小雅兰.的博客-CSDN博客

顺序表存在一些问题:

  • 中间/头部的插入删除,时间复杂度为O(N)
  • 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  • 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

单链表——“数据结构与算法”  

单链表——“数据结构与算法”  

单链表——“数据结构与算法”  

单链表——“数据结构与算法”

 思考:如何解决以上问题呢?下面给出了链表的结构来看看。


 链表

链表的概念及结构

概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

 单链表——“数据结构与算法”

单链表——“数据结构与算法”

现实中 数据结构中

 单链表——“数据结构与算法”


 结构体里面的数据类型:

typedef int SLTDataType;

定义一个结构体,结构体内部嵌套了一个结构体的指针:

这个就是单链表

typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

 单链表的打印:

//单链表的打印
void SLTPrint(SLTNode* phead)
{
	//可以不需要断言
	//因为:空链表也是可以打印的
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

单链表——“数据结构与算法”

意思是:首先,定义一个结构体的指针,该指针指向1,然后,对于cur,cur->data表示的是此结构体中的整型数据,cur->next表示的是2的地址,把cur->next赋值给cur,就是把这几块不连续的空间链接起来

单链表——“数据结构与算法”

单链表——“数据结构与算法”

单链表——“数据结构与算法”

表示:phead存的是第一个结点的地址,cur也存的是第一个节点的地址,就是把phead赋值给cur 

 头插

单链表——“数据结构与算法”

//头插
void SLPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	//assert(*pphead);
	//不能断言,链表为空,也需要能插入
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	newnode->next = *pphead;
	*pphead = newnode;
}

 单链表——“数据结构与算法”

 单链表——“数据结构与算法”

测试一下头插的功能:

void TestSList1()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
}
int main()
{
	TestSList1();
	return 0;
}

 单链表——“数据结构与算法”

在写这段代码的过程中,很容易犯错误,可能会有很多人这样写代码:

//头插
void SLPushFront(SLTNode* phead, SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	newnode->next = phead;
	phead = newnode;
}
void TestSList1()
{
	SLTNode* plist = NULL;
	SLPushFront(plist, 1);
	SLPushFront(plist, 2);
	SLPushFront(plist, 3);
	SLPushFront(plist, 4);
	SLPushFront(plist, 5);
	SLTPrint(plist);
}
int main()
{
	TestSList1();
	return 0;
}

这是一个十分经典的错误:

单链表——“数据结构与算法”

传值调用了!!!

实参是形参的一份临时拷贝,对形参的修改并不会影响实参,所以phead的改变并不会影响plist

单链表——“数据结构与算法”

举一个简单的例子:Swap

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	Swap(&a, &b);
	printf("%d %d\n", a, b);
	return 0;
}

毫无疑问,这样写确实是正确的。

单链表——“数据结构与算法”

有的人在这边可能就会想:是不是只要用了指针就可以了呢?

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int main()
{
	int* px = 10;
	int* py = 20;
	Swap(px, py);
	printf("%d %d\n", px, py);
	return 0;
}

 这样写,那是绝对不行的,接下来,来看看正确的写法:

void Swap(int** p1, int** p2)
{
	int* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int main()
{
	int* px = 10;
	int* py = 20;
	Swap(&px, &py);
	printf("%d %d\n", px, py);
	return 0;
}

单链表——“数据结构与算法”


我们会发现,在后续很多函数中,都需要用到创建结点这样一个功能,所以,可以把此功能封装成一个函数

//创建结点
void BuyLTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;//就相当于初始化一下
}

尾插

单链表——“数据结构与算法”

从指向1的地址变为指向2的地址 

单链表——“数据结构与算法”

循环所做的事

单链表——“数据结构与算法”

 单链表——“数据结构与算法”

单链表——“数据结构与算法”

//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuyLTNode(x);
	//1.空链表
	//2.非空链表
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;//tail->next本质是解引用,用tail的值找到指向的那个内存块,在内存块里面找到tail
		}
		tail->next = newnode;
	}
}

 测试一下尾插的功能:

void TestSList2()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
}
int main()
{
	TestSList2();
	return 0;
}

单链表——“数据结构与算法”

下面,来更好地解释一下为什么这边需要用到二级指针:

void func1(int* p)
{
	*p = 10;
}
void func2(int** pp)
{
	*pp = (int*)malloc(sizeof(int) * 10);
}
void func3(SLTNode* pnode)
{
	pnode->next = NULL;
}
void func4(SLTNode** ppnode)
{
	*ppnode = NULL;
}
int main()
{
	//要改变int,就要传int的地址
	int a = 0;
	func1(&a);
	//要改变int*,就要传int*的地址
	int* ptr = NULL;
	func2(&ptr);
	//要改变结构体,就要传结构体的地址
	SLTNode node;
	func3(&node);
	//要改变结构体的指针,传结构体的指针的地址
	SLTNode* pnode;
	func4(&pnode);
	return 0;
}

尾删

一个典型的错误的写法:野指针问题

单链表——“数据结构与算法”

 单链表——“数据结构与算法”

解决方式:

找到尾结点以及它的前一个结点

 单链表——“数据结构与算法”

//尾删
void SLPopBack(SLTNode** pphead)
{
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	assert(*pphead);
	SLTNode* prev = NULL;//前一个结点
	SLTNode* tail = *pphead;
	//找尾
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}

 还可以找倒数第二个

//尾删
//找倒数第二个
void SLPopBack(SLTNode** pphead)
{
	//没有结点(空链表)
	//一个结点
	//多个结点
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	assert(*pphead);//暴力的检查

	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* tail = *pphead;
		//找尾
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
	
}

测试一下尾删的功能:

void TestSList3()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
	SLPopBack(&plist);
	SLPopBack(&plist);
	SLTPrint(plist);
}

 单链表——“数据结构与算法”

头删

头删和尾删都有三种情况:

  • 没有结点(也就是空链表)
  • 有一个结点
  • 有多个结点

单链表——“数据结构与算法”

//头删
void SLPopFront(SLTNode** pphead)
{
	//没有结点(空链表)
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	assert(*pphead);//暴力的检查
	//链表为空,不能头删
	//一个结点
	//多个结点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* del = *pphead;//不能直接free掉
		//如果直接free的话,就找不到下一个结点的地址啦
		*pphead = del->next;
		free(del);
	}
}

测试一下头删的功能:

void TestSList4()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
	SLPopBack(&plist);
	SLPopBack(&plist);
	SLTPrint(plist);
	SLPopFront(&plist);
	SLPopFront(&plist);
	SLTPrint(plist);
}

 单链表——“数据结构与算法”


单链表——“数据结构与算法”

 单链表查找

//头插、尾插、头删、尾删都要修改链表,所以要传二级指针
//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	//不用assert,因为空链表也是可以查找的
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

测试一下单链表查找的功能:

void TestSList4()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
	SLPopBack(&plist);
	SLPopBack(&plist);
	SLTPrint(plist);
	SLPopFront(&plist);
	SLPopFront(&plist);
	SLTPrint(plist);
	SLTNode* pos = SLTFind(plist, 2);
	pos->data = 30;
	SLTPrint(plist);

}

 单链表——“数据结构与算法”


任意位置数据的插入(pos之前插入)

单链表——“数据结构与算法”

//在pos的位置之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	if (*pphead == pos)
	{
		SLPushFront(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuyLTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

后插

//在pos的位置之后插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuyLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

测试一下前插和后插的功能:

void TestSList5()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
	SLPopBack(&plist);
	SLPopBack(&plist);
	SLTPrint(plist);
	SLPopFront(&plist);
	SLPopFront(&plist);
	SLTPrint(plist);
	SLTNode* pos = SLTFind(plist, 3);
	if (pos != NULL)
	{
		SLTInsert(&plist, pos, 20);
	}
	SLTPrint(plist);
	pos = SLTFind(plist, 2);
	if (pos != NULL)
	{
		SLTInsertAfter(pos, 30);
	}
	SLTPrint(plist);
}

 单链表——“数据结构与算法”

删除pos位置的值

//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	if (pos == *pphead)
	{
		SLPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

后删

//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
}
void TestSList5()
{
	SLTNode* plist = NULL;
	SLPushFront(&plist, 1);
	SLPushFront(&plist, 2);
	SLPushFront(&plist, 3);
	SLPushFront(&plist, 4);
	SLPushFront(&plist, 5);
	SLTPrint(plist);
	SLPushBack(&plist, 6);
	SLPushBack(&plist, 7);
	SLPushBack(&plist, 8);
	SLPushBack(&plist, 9);
	SLPushBack(&plist, 10);
	SLTPrint(plist);
	SLPopBack(&plist);
	SLPopBack(&plist);
	SLTPrint(plist);
	SLPopFront(&plist);
	SLPopFront(&plist);
	SLTPrint(plist);
	SLTNode* pos = SLTFind(plist, 3);
	if (pos != NULL)
	{
		SLTInsert(&plist, pos, 20);
	}
	SLTPrint(plist);
	pos = SLTFind(plist, 2);
	if (pos != NULL)
	{
		SLTInsertAfter(pos, 30);
	}
	SLTPrint(plist);
	pos = SLTFind(plist, 7);
	if (pos != NULL)
	{
		SLTErase(&plist,pos);
	}
	SLTPrint(plist);

}

单链表——“数据结构与算法”


源代码如下:

SList.h的内容:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;
//单链表的打印
void SLTPrint(SLTNode* phead);
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x);
//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x);
//头删
void SLPopFront(SLTNode** pphead);
//尾删
void SLPopBack(SLTNode** pphead);
//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在pos的位置之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos,SLTDataType x);
//在pos的位置之后插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置之前的值
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos);

SList.c的内容:

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
//单链表的打印
void SLTPrint(SLTNode* phead)
{
	//可以不需要断言
	//因为:空链表也是可以打印的
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	//assert(*pphead);
	//不能断言,链表为空,也需要能插入
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;

	newnode->next = *pphead;
	*pphead = newnode;
}
//创建结点
SLTNode* BuyLTNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->data = x;
	newnode->next = NULL;//就相当于初始化一下
	return newnode;
}
//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	//assert(*pphead);
	//不能断言,链表为空,也需要能插入
	SLTNode* newnode = BuyLTNode(x);
	//1.空链表
	//2.非空链表
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;//tail->next本质是解引用,用tail的值找到指向的那个内存块,在内存块里面找到tail
		}
		tail->next = newnode;
	}
}
尾删
// 找倒数第一个
//void SLPopBack(SLTNode** pphead)
//{
//	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
//	assert(*pphead);
//	SLTNode* prev = NULL;//前一个结点
//	SLTNode* tail = *pphead;
//	//找尾
//	while (tail->next != NULL)
//	{
//		prev = tail;
//		tail = tail->next;
//	}
//	free(tail);
//	prev->next = NULL;
//}
//尾删
//找倒数第二个
void SLPopBack(SLTNode** pphead)
{
	//没有结点(空链表)
	//一个结点
	//多个结点
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	assert(*pphead);//暴力的检查

	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* tail = *pphead;
		//找尾
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
	
}
//头删
void SLPopFront(SLTNode** pphead)
{
	//没有结点(空链表)
	assert(pphead);//链表为空,pphead也不能为空,因为它是头指针plist的地址
	assert(*pphead);//暴力的检查
	//链表为空,不能头删
	//一个结点
	//多个结点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* del = *pphead;//不能直接free掉
		//如果直接free的话,就找不到下一个结点的地址啦
		*pphead = del->next;
		free(del);
	}
}
//头插、尾插、头删、尾删都要修改链表,所以要传二级指针
//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	//不用assert,因为空链表也是可以查找的
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
//在pos的位置之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	if (*pphead == pos)
	{
		SLPushFront(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLTNode* newnode = BuyLTNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}
//在pos的位置之后插入
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = BuyLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
//删除pos位置的值
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	if (pos == *pphead)
	{
		SLPopFront(pphead);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}
//删除pos位置之后的值
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	SLTNode* next = pos->next;
	pos->next = next->next;
	free(next);
}

好啦,小雅兰今天的单链表的内容就到这里啦,内容还是非常多的,也比较难,小雅兰会继续加油学习的,冲冲冲!!!

单链表——“数据结构与算法”文章来源地址https://www.toymoban.com/news/detail-425308.html

到了这里,关于单链表——“数据结构与算法”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】单链表经典算法题的巧妙解题思路

    目录 题目 1.移除链表元素 2.反转链表 3.链表的中间节点 4.合并两个有序链表 5.环形链表的约瑟夫问题 解析 题目1:创建新链表 题目2:巧用三个指针 题目3:快慢指针 题目4:哨兵位节点 题目5:环形链表   介绍完了单链表,我们这次来说几个经典的题目,本篇的题目衔接下一

    2024年04月28日
    浏览(63)
  • 【算法基础】数据结构| 单链表+双链表 代码实现+图解+原理

    博主简介: 努力学习的预备程序媛一枚~ 博主主页: @是瑶瑶子啦 所属专栏: Java岛冒险记【从小白到大佬之路】 因为瑶瑶子正在备战蓝桥杯和校内ACM选拔赛,最近在学习算法相关的知识。我是借助 AcWing网站 来学习的,这篇文章是我学习就我学习内容的一个笔记,其中的一些

    2024年02月01日
    浏览(61)
  • 【算法与数据结构】 C语言实现单链表队列详解

    前面我们学习了队列的顺序表的实现,本节将用单链表实现队列。 队列也可以数组和链表的结构实现, 使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低 。下面我们先复习一下队列的基本概念: 队列:只允许在一端进行插入

    2024年04月11日
    浏览(60)
  • 【数据结构与算法】单链表的增删查改(附源码)

      这么可爱的猫猫不值得点个赞吗 😽😻 目录 一.链表的概念和结构 二.单链表的逻辑结构和物理结构 1.逻辑结构  2.物理结构 三.结构体的定义 四.增加 1.尾插   SListpushback 2.头插  SListpushfront 五.删除 1.尾删  SListpopback 2.头删  SListpopfront 六.查找  插入  释放   打印 1.查找

    2024年02月02日
    浏览(75)
  • 单链表的建立(头插法、尾插法)(数据结构与算法)

    如果要把很多个数据元素存到一个单链表中,如何操作? 1.初始化一个单链表 2. 每次取一个数据元素,插入到表尾/表头 尾插法建立的单链表元素顺序与输入数据集合的顺序相同,即按照输入数据的顺序排列。 使用尾插法建立单链表的一个常见应用是在计算机科学中进行数据

    2024年04月11日
    浏览(44)
  • 【数据结构与算法】深入浅出:单链表的实现和应用

      🌱博客主页:青竹雾色间. 😘博客制作不易欢迎各位👍点赞+⭐收藏+➕关注  ✨ 人生如寄,多忧何为  ✨ 目录 前言 单链表的基本概念 节点 头节点 尾节点 单链表的基本操作 创建单链表 头插法: 尾插法: 插入(增)操作  删除(删)操作: 查找(查)操作: 修改(改

    2024年02月08日
    浏览(75)
  • 【一起学数据结构与算法】快速教你了解并实现单链表

    此篇是对单链表知识的学习和实现,基本上大体的方法实现和思路都已经表达,如果有不对的地方,还请各位大佬多多指教! 单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:元素

    2024年02月19日
    浏览(43)
  • C语言简单的数据结构:单链表的有关算法题(2)

    接着我们介绍后面的三道题,虽然代码变多了但我们的思路更加通顺了 题目链接:https://leetcode.cn/problems/merge-two-sorted-lists/ 创建新链表,遍历原链表,将节点值小的进行尾插到新链表中 这里要多次进行对NULL的判断,开始传入列表,中间newHead的判断,循环出来一个为NULL的判断

    2024年04月15日
    浏览(64)
  • 第一百零六天学习记录:数据结构与算法基础:单链表(王卓教学视频)

    结点在存储器中的位置是任意的,即逻辑上相邻的数据元素在物理上不一定相邻 线性表的链式表示又称为非顺序映像或链式映像。 用一组物理位置任意的存储单元来存放线性表的数据元素。 这组存储单元既可以是连续的,也可以是不连续的,甚至是零散分布在内存中的任意

    2024年02月16日
    浏览(55)
  • 【数据结构与算法】顺序表与链表(单链表和双链表)超详解图示与源码。

                                                       大家好,今天我们来学习数据结构中的顺序表与链表!源码在最后附上 首先我们先来认识一下 顺序表 :                                       **如上图所示:很多人会以为数组就是顺序表,顺序表就是数组,这

    2024年02月21日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包