代码
//
// Created by qpn on 2022/3/25.
//
#include <malloc.h>
#include "stdio.h"
/*
* 构建一个链表的结构体
*/
typedef struct Link {
int ele;
struct Link *next;
} link;
link *initLink(){
/*
* 创建一个头结点
*/
link *p = (link*)malloc(sizeof(link));
/*
* 初始化一个指向头结点的指针
*/
link *temp = p;
for (int i = 0; i < 5; ++i) {
/*
* 每次都创建一个新的节点,给节点
*/
link *a = (link*) malloc(sizeof(link));
a ->ele=i;
a->next=NULL;
temp->next=a;
temp=temp->next;
}
return p;
}
void traverse_link(link *p){
link *head = p;
while (head->next!=NULL){
head=head->next;
printf("value:%d\n",head->ele);
}
printf("finished");
}
int main(){
link *p = initLink();
traverse_link(p);
return 0;
}
分析
首先我们要知道头指针 temp
的存在是为了标定头结点的位置,因为最后你要返回一个链表(return p
)其实是返回链表的头结点的地址,所以我们必须要保留头结点的位置。
-
这个时候你可能会有疑问?不保留头结点的位置他还能丢了?他不就在内存里面么。
-
话虽这么说,但是假设没有指向头结点的指针,那么在产生新结点并链接起来的过程就会不断发生
p=p->next
这样到最后,p
的地址将会是链表最后一个结点的地址,如果这时候返回p
那返回的就不是一个完整的链表了,而是最后一个指向NULL
的空结点。 -
因此,聪明的前辈们选择用一个指向头结点的指针
temp
,刚创建头结点的时候,temp
指向的是头结点,相当于一个头结点p
的分身,然后创建后面的结点的时候,temp
不断进行temp=temp->next
从而保持头结点不需要进行p=p->next
也能把后面的链表链接起来。 -
这样当链表构建完成,
temp
指向了链表的最后一个结点,但头结点p
依然在原来的位置,相当于temp
完成了这个只有去路没有归路的活!真是个勇士! -
如果依然感觉不够直观,可以把
for
循环中的代码改成这样,看看最后会打印出什么样的输出:
for (int i = 0; i < 5; ++i) {
/*
* 每次都创建一个新的节点,给节点
*/
link *a = (link*) malloc(sizeof(link));
a ->ele=i;
a->next=NULL;
p->next=a;
p=p->next;
}
return p;