前言
好久没写博客了,寒假在家里都快躺废了。最近打算巩固一下C语言,没想到一个小小的链表竟能奈我何,看来真是学艺不精啊。
代码
为了避免读者头晕,先上简单的,能编译通过的代码,暂时不考虑程序健壮性,毕竟我们只需考虑创建链表的本质,其他细枝末节的可以暂且不管。
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
}Node;//创建节点结构体
int main(){
int i;
int n=2;//创建3个节点(一个头节点,两个数据节点)
Node* head = (Node*)malloc(sizeof(Node));//创建头节点
Node* p=head;
head->val=666;
head->next=NULL;
for(i=0;i<n;i++){
Node* end=(Node*)malloc(sizeof(Node));//创建尾节点
p->next=end;
end->val=i;
end->next=NULL;
p=end;
}
}
图解
首先,创建链表可以大致分为两个过程:1.分配内存 2.移动p指针
1.分配内存
程序执行完,内存里的情况大致可以抽象成以下图像:
从左往右看,左侧的指针和右侧的内存空间形成映射关系
从上往下看,右侧的内存块(节点)前后连接
以上是从结果来看,分配完内存后的情况
注意:其实end指针是一个局部变量,每一次分配内存的end指针变量都是同名但却不同的变量,图中在后面加了一个括号以示区分
2.移动p指针
我们来逐行解释一下代码
Node* head = (Node*)malloc(sizeof(Node));//创建头节点
Node* p=head;
对应以下示意图
head指针和p指针都指向同一块内存地址(地址1)
这里插一句,用malloc分配给head内存空间,那么head指针和地址1之间就形成了“羁绊”,也就是说,要想改变head的指向(实际上就是改变head的内容),就得free(head),这也是为什么需要指针p也指向地址1,因为p可以随意改变指向
for(i=0;i<n;i++){
Node* end=(Node*)malloc(sizeof(Node));//创建尾节点
p->next=end;
end->val=i;
end->next=NULL;
p=end;
}
现在逐行解释以上i=0时的情况,
Node* end=(Node*)malloc(sizeof(Node));//创建尾节点
p->next=end;
end->next=NULL;
p=end;
以此类推,读者可以自己尝试画剩下的过程图,说真的,一图抵千言
最终代码
完善后的代码如下
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
int val;
struct Node* next;
}Node;//创建节点结构体
int main(){
int i;
int n=2;//创建2个数据节点(加上头节点,总共有3个节点)
Node* head = (Node*)malloc(sizeof(Node));//创建头节点
if (head == NULL) { // 检查malloc是否成功
printf("Memory allocation failed for head node.\n");
return 1; // 返回非零值表示错误
}
Node* current=head;
head->val=666;
head->next=NULL;
for(i=0;i<n;i++){
Node* end=(Node*)malloc(sizeof(Node));//创建尾节点
if (end == NULL) { // 检查malloc是否成功
printf("Memory allocation failed for node %d.\n", i);
// 释放之前已经分配的内存
while (current != NULL) {
Node* temp = current;
current = current->next;
free(temp);
}
return 1; // 返回非零值表示错误
}
current->next=end;
end->val=i;
end->next=NULL;
current=end;
}
// 遍历并打印链表(可选)
current = head;
while (current != NULL) {
printf("%d ", current->val);
current = current->next;
}
printf("\n");
current= head;
while (current != NULL) {
Node* temp = current;
current = current->next;
free(temp);
}
system("pause");
return 0;
}
运行结果
结语
总结了以下,其实难点还是在于指针,指针理解的不够深刻,在这方面可以多画画示意图可以有助于理解