C语言手撕单链表
一、链表的概念
链表是一种物理存储结构上非连续、非顺序的存储结构,也就是内存存储不是像顺序表那么连续存储,而是以结点的形式一块一块存储在堆上的(用动态内存开辟)。
既然在内存上不是连续存储,那我们如何将这一块一块单独的空间链接起来呢?
我们可以创建一个结构体充当我们的结点,里面分别存放数据(数据域)和下一个结点的地址(指针域),这样我们就可以将一块一块单独的空间链接起来了。
而单链表,顾名思义就是单向链接的链表,效果如同下图
前言:
在讲解单链表的各个接口前,很有必要讲解以下单链表的物理内存到底是如何存储的,先掌握这个,接下来的讲解就会更容易理解
头结点指向的地址就是第一个结点的总地址
第一个结点的指针域指向的是第二个结点的总地址,所以分为两个地址
一个是结点的总地址,另一个是结点总地址里面的next指针存放的指针域的地址,这个指针域的地址又指向了下一个结点的总地址。
看下面的图解内存存储的数据,实际中是没有箭头的,把箭头去掉,才是内存中真正的存储模式
二、接口实现
对数据结构我们一般采用增删查改去实现。
-
-
-
-
-
-
typedef int SLTDataType;
-
-
typedef struct SListNode
-
{
-
SLTDataType data;//数据域
-
struct SListNode* next;//指针域
-
}SLTNode;
-
-
void SLTPrint(SLTNode* phead);
-
-
SLTNode* BuySListNode(SLTDataType x);
-
-
void SLTPushBack(SLTNode** phead, SLTDataType x);
-
-
void SLTPushFront(SLTNode** phead, SLTDataType x);
-
-
void SLTPopFront(SLTNode** phead);
-
-
void SLTPopBack(SLTNode** phead);
-
1、遍历单链表打印函数
一般需要创建一个临时变量去接收头结点
-
//遍历链表肯定需要头结点
-
void SLTPrint(SLTNode* phead)
-
{
-
SLTNode* cur = phead;//一般需要临时创建变量
-
while (cur != NULL)
-
{
-
printf("%d->", cur->data);
-
cur = cur->next;
-
}
-
printf("NULL");
-
}
2、创建单链表函数
-
SLTNode* BuySListNode(SLTDataType x)
-
{
-
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
-
if (newnode == NULL)
-
{
-
perror(malloc);
-
exit(-1);
-
}
-
newnode->data = x;
-
newnode->next = NULL;
-
}
3、尾插
需要分情况讨论,
- 如果链表本身是空,直接改变头结点的指针,直接指向新建的结点
- 若不为空,需要找到尾结点
TIP:何时用指针变量,何时用二级指针?
改变结构体本身,需要结构体指针
改变结构体指针,需要结构体指针指针(二级指针),并且要有解引用的操作!
刚才第一种情况,直接将头结点的指针改变成新指针的地址,这种直接改变指针的模式,就需要二级指针,进行解引用才能达到目的。
-
void SLTPushBack(SLTNode** phead, SLTDataType x)
-
{
-
//需要分情况讨论,如果链表本身是空
-
if (*phead == NULL)
-
{
-
SLTNode* newnode = BuySListNode(x);
-
//改变结构体本身,需要结构体的指针
-
//改变结构体指针,需要结构体指针指针(二级指针),并且要有解引用的操作
-
*phead = newnode;
-
}
-
else
-
{
-
//先找尾结点
-
SLTNode* newnode = BuySListNode(x);
-
SLTNode* tail = *phead;
-
while (tail->next != NULL)
-
{
-
tail = tail->next;
-
}
-
tail->next = newnode;
-
}
-
-
}
4、头插
头插肯定需要二级指针,因为每次头插都要改变头指针指向的位置
-
//头插肯定需要二级指针,因为每次头插都要改变头指针指向的位置
-
void SLTPushFront(SLTNode** phead, SLTDataType x)
-
{
-
SLTNode* newnode = BuySListNode(x);
-
newnode->next = *phead;
-
*phead = newnode;
-
}
5、尾删
分三种情况
- 第一种是链表为空,需要assert断言检查
- 第二种链表中只有一个结点,需要改变结构体指针,因此函数传参也是需要二级指针
- 第三种链表有多于一个的结点,需要先找到尾结点。
-
void SLTPopBack(SLTNode** pphead)
-
{
-
//分三种情况
-
// 第一种就是链表为空
-
assert(*pphead);
-
// 第二种链表只有一个结点,需要改变结构体指针
-
if ((*pphead)->next == NULL)
-
{
-
free(*pphead);
-
pphead = NULL;
-
}
-
//第三种链表多于一个结点
-
else
-
{
-
SLTNode* tail = *pphead;
-
SLTNode* tailprev = NULL;
-
while (tail->next != NULL)
-
{
-
tailprev = tail;
-
tail = tail->next;
-
}
-
free(tail);
-
tailprev->next = NULL;//严格要求尾指针前一个的next指向null
-
}
-
}
6、头删
不需要分类讨论,直接改变头节点的指针指向,但是需要一个临时变量存储结点,便于后面的操作
-
void SLTPopFront(SLTNode** phead)
-
{
-
assert(*phead);
-
SLTNode* newnode = (*phead)->next;
-
free(*phead);
-
*phead = newnode;
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgccaea
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13