单链表详解(如何实现单链表)

本文详细介绍了单链表的概念、结构以及其实现,包括接口函数如打印、扩容、插入和删除操作。同时对比了单链表与顺序表的优缺点,强调了单链表在随机访问方面的局限性。
摘要由CSDN通过智能技术生成

ab26cc04595f467d978356fbb6c6fd0a.gif

文章目录

前言


顺序表的缺点

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

针对顺序表的缺点,设计了链表


一、单链表是什么?

ae4dc5612f4840b997c5d7fe639174d1.png

链表是数据结构之一,其中的数据呈线性排列。在链表中,数据的添加和删除都较为方便,就是访问比较耗费时间。

1.2结构

typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;

}SLTNode;

这就是单链表的经典结构

其实一个链表还分逻辑模型和物理模型

逻辑模型

facb5ff9a1f74c09881685afa590cfea.png

物理模型

92872284be4e41a9bc2905ba7741dc99.png

二.单链表的实现(接口函数的实现)

2.1打印

打印只有一个细节就是cur = cur->next,cur是一个结构体指针,可以通过->去访问成员,他的意思就是往下去遍历。

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
}

2.2检查扩容

和之前的顺序表的思路是一样的,单链表也是需要检查扩容的,如果满了就要扩,如果少了就要增。

SLTNode* BuyListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	return newnode;
}

2.3尾插

a810a3fba58a46e2b266443f495b0cd2.png

利用两个指针,先检查扩容,如果是空的就增容,然后先找到尾,然后在把新开辟的内存链接起来就可以了。

void SListPushBack(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找到尾节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newnode;
	}
}

2.4头插

6d9f0d68e1224f2b951b22a46f7cbd2f.png

注意要不要传2级指针,只有判断是否使用phead

void SListPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;

}

2.5尾删

尾删有两个方法,两个指针和单指针

两个指针法

将最后一组元素释放,在将最后一个元素置空,但是一个节点要单独考虑

void SListPopBack(SLTNode** pphead)
{
	assert(*pphead != NULL);
		if ((*pphead)->next = NULL)
		{
			free(*pphead);
			*pphead = NULL;
		}
		else
		{
			SLTNode* prev = NULL;
			SLTNode* tail = *pphead;
			while (tail->next != NULL)
			{
				prev = tail;
				tail = tail->next;
			}
			free(tail);
			tail = NULL;
			prev->next = NULL;
		}
}

单指针法

void SListPopBack(SLTNode** pphead)
{
    SLTNode*tail=*pphead;	
    assert(*pphead != NULL);
		if ((*pphead)->next = NULL)
		{
			free(*pphead);
			*pphead = NULL;
		}
   while(tail->next->next!=NULL)
  {
        tail=tail->next;
}
          free(tail->next);
      tail->next=NULL;
}

2.6头删

保存下一节点next,删除头节,点将头节点赋值为next。

void SListPopFront(SLTNode** pphead)
{
	assert(*pphead != NULL);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

2.7查找

SLTNode* SListFind(SLTNode* phead, SLTDateType x)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}

2.8在pos位置之前去插入一个节点

5a565a46e4484286b8b3bb9c313c2270.png

先要找到他的位置,找到pos之前的位置

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else//找到pos之前的位置
	{
		SLTNode* posprev = *pphead;
		while (posprev->next != pos)
		{
			posprev = posprev->next;
		}
		posprev->next = newnode;
		newnode->next = pos;
	}
}

2.8在pos位置之后去插入一个节点

void SListInsertAfter(SListNode* pos, SListData x)
{
	assert(pos);
	SListNode* newnode = BuyListNode(x);
	SListNode* next = pos->next;
	pos->next = newnode;
	pos->next->next = next;
}

2.9在pos位置去删去一个结点(头要特殊处理)

void SListInsert(SListNode** pphead, SListNode* pos, SListData x)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead) 
	{
		*pphead=pos->next;
         free(pos);
	}
	else
	{
		SListNode* pre = *pphead;//找到前一个
		while (pre->next != pos)	
		{
			pre = pre->next;
		}
		pre->next = pos->next;//前一个指向后一个
		free(pos);
	}
}

3.0销毁,还原

void SListDestory(SLTNode**pphead)
{
       SLTNode*cur=*pphead;
      while(cur!=NULL)
{
     SLTNode*next=cur->next;
     free(cur);
      cur=next;
}
      *pphead=NULL;
}
   

 

 


总结

单链表的缺点就是不可以随机访问,而顺序表却可以做到,说明单链表也有缺陷,那什么结构可以让我们更好?只有继续的学习才会知道。

 

 

 

  • 43
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 40
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 40
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LaNzikinh篮子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值