提示:本文章参考知乎大佬和一位博主大佬
单向链表
- 1.前置知识(部分最好记忆)
- 1.1 链表组成
- 1.2 链表插入分三种情况
- 1.2.1头插
- 1.2.2 中间插
- 1.2.2 结尾插
- 1.3 链表的删除
- 1.5
- 1.6
- 1.7
- 2.链表各种接口的实现
- 2.1 链表的打印
- 2.1 链表的节点的申请
- 2.2 单链表节点增加
- 2.2.1 单链表指定位置插入
- 2.2.1 单链表尾插
- 2.3 单链表头插
1.前置知识(部分最好记忆)
1.1 链表组成
链表由很多节点组成,每个节点其实是一个结构体变量
当链表无数据,也就是phead为NULL。因为phead是指向第一个存有数据的结点的,也就是第一个节点的地址。
在定义结构体类型后,可以通过
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
创建一个结构体变量(空间),返回结构体变量的地址,也就是节点的地址。
每个节点由二个属性(定义结构体类型时定义的),一个为data(存储数据),一个next(存储下一个节点的地址)
尾节点为最后一个节点,其后面的无节点(也就是ptail->next 为NULL)
这样在前一个节点连接后一个节点,并为尾节点连接空指针后,我们只需知道头节点的地址,即可根据连接关系,访问整个链表。
所以一般增删查找,都会需要传参ptail(头节点指针) 也就是链表的入口(链表关键参数)。
1.2 链表插入分三种情况
1.2.1头插
头插之后,phead位置改变,需要重新赋值 同时插入的节点需要链接后面
1.2.2 中间插
插入的节点,需要连接前面和后面
1.2.2 结尾插
插入的节点,需要连接前面和后面指向NULL
1.3 链表的删除
1.5
1.6
1.7
2.链表各种接口的实现
2.1 链表的打印
void SListPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;//相当于指针的后移一位
}
printf("NULL\n");
}
void SListPrint(SLTNode* phead)
{
SLTNode* cur = phead;
while (cur->next != NULL)
{
cur = cur->next;//相当于指针的后移一位
printf("%d->", cur->data);
}
printf("NULL\n");
}
2.1 链表的节点的申请
// 动态申请一个结点
SLTNode* BuySLTNode(SLTDataType x)
{
//同样不需要断言
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//先创建个结点
if (newnode == NULL)//如果malloc失败
{
perror("malloc fail");
return NULL;
}
//如果malloc成功
newnode->data = x;//插入的数据
newnode->next = NULL;//初始化为空
return newnode;//返回newnode 节点地址
}
2.2 单链表节点增加
2.2.1 单链表指定位置插入
2.2.1 单链表尾插
tail为空指针的前一个节点 尾节点指向NULL 即tail->next
// 单链表尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
assert(pphead);//pphead是phead的地址,不能为空
SLTNode* newnode = BuySLTNode(x);
//找尾(尾插之前先找到尾)
if (*pphead == NULL)//若链表为空
{
*pphead = newnode;//把新节点作为头结点
}
else//若链表不为空
{
SLTNode* tail = *pphead;
while (tail->next != NULL)
//tail为空指针的前一个节点 //尾节点指向NULL 即tail->next
//对于不为空的链表:尾插的本质是原尾结点要存新尾结点的地址
{
tail = tail->next;
}
tail->next = newnode;//挪动的指针指向新节点 也就是挪动的指针等于新节点的指针
/*有些同学会写成:----错误写法
while (tail != NULL)
{
tail = tail->next;
}
tail = newnode;*/
}
}
2.3 单链表头插
// 单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
//发现plist不管是否为空,头插的方法都一样
SLTNode* newnode = BuySLTNode(x);
newnode->next = *pphead;
*pphead = newnode;
}