以如下为例:
typedef int SLTDataType;
typedef struct SListNode
{
SLTDataType data;
struct SListNode* next;
}SLTNode;
若想在此链表中尾插一个数据(新的结构体):
思路:
利用一个指针tail,找到链表的尾部,在尾部的 next 指针中连接好新的元素
一、代码与注释
void SLPushBack(SLTNode** pphead, SLTDataType x)
{
SLTNode* newnode = BuyLTNode(x); //将newnode指向新开的结构体空间
// 1、空链表
// 2、非空链表
if (*pphead == NULL) //本身链表为空
{
*pphead = newnode; //直接将开辟的新结构体空间,让*pphead指向新开辟的空间
}
else
{
SLTNode* tail = *pphead; //解引用,变成一级指针,因此:tail可以找到实参,并对实参进修操作、修改!
//尾节点的特点是 tail -> next为空
while (tail->next != NULL) //不可以tail != NULL 如果是这样的话,tail会最终直接指向下一个链表,而不是将其与紧接着的tail - > next这个结构体指针连接起来(可以理解为火车脱节)
{
tail = tail->next;
}
//为结构体指针 next 赋值。(- >可以修改实参)
//整体逻辑:二级指针->一级指针->成员(成员又是一个结构体指针)
tail->next = newnode; // ->再次解引用 (结构体的解引用,使用的符号是 - > ,此语句的含义是:为结构体中的next指针赋值,指向newnode空间)
}
}
二、指针解析(好好看完注释!)
1.传参传二级指针
理由:
对应代码
SLTNode* tail = *pphead; //解引用,变成一级指针,因此:tail可以找到实参,并对实参进修操作、修改!
传入二级指针之后,通过解引用,可以让tail指针找到实参
2.
代码解析:
tail->next = newnode; // ->再次解引用 (结构体的解引用,使用的符号是 - > ,此语句的含义是:为结构体中的next指针赋值,指向newnode空间)
此处的——>可以理解为结构体中的解引用操作!
tail是一级指针,并且是结构体指针,可以通过——>找到结构体成员变量 next。
值得一提的是,next作为成员变量,本身就是一个结构体指针!
此代码的意思就是:让 一级指针 tail 找到结构体成员变量:next,并且让其指向newnode开辟的空间。
题外话:
作为链表,值得一提的是,新开辟的newnode空间并非在物理上是连续的,但是却能让next指针找到这块空间,从而让物理上不连续的空间,在逻辑上可以用连续的思维去分析。