单链表的基本操作

单链表的基本介绍

单链表是顺序表的一种,顺序表指的是可以线性排列,具有同种元素的有限序列。比如数组是顺序表的一种,它的空间上是连续的,逻辑上也是连续的。
而链表是由指针进行连接的,空间上是不连续的,逻辑上是连续的。

链表与数组的区别

对于链表它是不支持随机访问的,因为它必须知道它的地址,要寻找上一个节点,而数组可以随机访问
在插入元素上,数组上可能要搬运元素,但是链表却可以任意插入,时间复杂度较高。
如果插入了许多元素,链表不需要扩容,而数组需要
对于元素频繁访问,数组会更好一点,对于任意位置插入和删除,链表会更好
顺序表的缓存利用率更高

链表的基本操作

前置

typedef  int SLDataType ;
typedef struct SListNode
{
	SLDataType data;
	struct SListNode* next;
}SL;

链表的创建

SL* BuySListNode(SLDataType x)
{
	SL* NewNode = (SL*)malloc(sizeof(SL));
	if (NewNode == NULL)
	{
		exit(-1);
	}
	NewNode->data = x;
	NewNode->next = NULL;
	return NewNode;
}

malloc一个节点,把内容传进去

链表的尾插

先找到尾,把新节点连接上去,

void SListPushBack(SL** pphead,SLDataType x)
{
	SL* NewNode = BuySListNode(x);
	if (*pphead == NULL)
	{
		*pphead = NewNode;
	}
	//当头节点为空的时候
	else
	{
		SL* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = NewNode;//tail->next为空
	}
	//找到尾节点尾节点的后面连接上新节点
}

链表的头插

我们是改变了头指针,所以传入指针的地址,所以是二重指针

void SListPushFront(SL** pphead, SLDataType x)
{
	SL* NewNode = BuySListNode(x);
	NewNode->next = *pphead;
	*pphead = NewNode;
	//让新节点连接上起始节点,再让新节点作为起始节点
}

链表的尾删

注意先判断是不是只有一个节点,如果是那么直接free,而且找到tail的next,再free,然后再置为空

void SListPopBack(SL** pphead)
{
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SL* tail = *pphead;
		/*while (tail->next != NULL)
		{
			tail = tail->next;
		}
		free(tail);
		tail = NULL;*/
		//如果直接freetail,那么链表的尾将会是一个野指针我们free tail的next
		while (tail->next->next)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}

链表的头删

先把第二个节点保存,以防找不到节点作为新头

void SListPopFront(SL** pphead)
{
	assert(*pphead);
	SL* cur = (*pphead)->next;;
	free(*pphead);
	*pphead = cur;
	//先把第二个节点保存
}

链表的查找

遍历链表没什么好说的

SL *SListFind(SL* phead, SLDataType x)
{
	assert(phead);
	SL* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else

		cur = cur->next;
	}
	return NULL;

}

链表的指定节点后插

后插的时候记住保存下一个节点

void SListInsertAfter(SL* pos, SLDataType x)
{
	SL* NewNode = BuySListNode(x);
	SL* cur = pos->next;
	
	
		pos->next = NewNode;
		NewNode->next = cur;
	
	
}

链表的指定位置前插

先看看指定位置是不是头节点,如果是也就是头插,如果不是,我们要找到指定位置的前一个节点进行保存。

void SListInsert(SL** pphead, SL* pos, SLDataType x)
{
	SL* NewNode = BuySListNode(x);
	if (pos == *pphead)
	{
		NewNode->next = *pphead;
		*pphead = NewNode;
	}
	else
	{
		//我们要找到pos的前一个位置才行
		SL* posPrev = *pphead;
		
		while (posPrev->next == pos)
		{

			posPrev = posPrev->next;
		}
		posPrev->next = NewNode;
		NewNode->next = pos;
	}
	
}

链表的删除

同样要找到指定节点的前一个,再进行删除

void SListErase(SL** pphead, SL* pos)
{
	assert(pos);
	if (*pphead == pos)
	{
		*pphead = (*pphead)->next;
		free(pos);
	}
	else
	{
		SL* posPrev = *pphead;

		while (posPrev->next != pos)
		{

			posPrev = posPrev->next;
		}
		posPrev->next = pos->next;
		free(pos);
		

	}
}

链表的销毁

先把下一个保存,以免找不到,然后遍历销毁

void SListDestory(SL** pphead)
{
	SL* p=*pphead;
	while (p)
	{

		*pphead = (*pphead)->next;
		free(p);
		p == NULL;
		p = *pphead;

	}
}

**

点个赞再走吧

**

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值