1、什么是链表
就是数据结构 -> 数据存放(集合)的思想
数组 :每一个元素的地址是连续的。
int arry[10] ={1,2,3,3,4,5,6,7,8,9,10};
这个空间就等于 4*10 = 40个字节。
1个字符 4个字节.
结构体:每一个元素
struct a {
int a ,b;
};
这个结构体空间就是16个字节 8*2;
一个字符 8个字节。
缺点:
不管是数组,还是结构体,他们无法的 其中的数据进行增加、删除和,因为地址是连续的。
链表:
链表的每一项元素都是一个结构体,在内存存储中不是连续的,是通过指针相连。
2.链表入门:
#include <stdio.h> // 引入标准输入输出库
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
int main()
{
int i; // 定义一个整数变量 i
int arry[] = {1, 2, 3}; // 定义一个整数数组 arry,并初始化为 1, 2, 3
int len = sizeof(arry) / sizeof(arry[0]); // 计算数组 arry 的长度
for(i = 0; i < len; i++)
{
printf("%d", arry[i]); // 循环输出数组 arry 的每个元素
}
putchar('\n'); // 输出一个换行符
struct Test t1 = {1, NULL}; // 定义并初始化结构体变量 t1,date 为 1,next 为 NULL
struct Test t2 = {2, NULL}; // 定义并初始化结构体变量 t2,date 为 2,next 为 NULL
struct Test t3 = {3, NULL}; // 定义并初始化结构体变量 t3,date 为 3,next 为 NULL
t1.next = &t2; // 将 t1 的 next 指针指向 t2
t2.next = &t3; // 将 t2 的 next 指针指向 t3
/*
t1.data 是结构体 t1 中的一个整数成员变量,表示输出第一个整数。
t1.next->data 是 t1 结构体中指向下一个节点的指针 next 所指节点的整数成员变量,表示输出第二个整数。
t1.next->next->data 是 t1 结构体中指向下一个节点的指针 next 所指节点中再次指向下一个节点的指针 next 所指节点的整数成员变量,表示输出第三个整数。
*/
printf("%d %d %d", t1.date, t1.next->date, t1.next->next->date); // 输出 t1 的 date,t2 的 date,t3 的 date
return 0; // 返回 0,表示程序正常结束
}
3.while 循环输出链表
#include <stdio.h> // 引入标准输入输出库
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
void printLink(struct Test *head)
{
struct Test *point;
point = head;
while(point != NULL){ //如果当前节点指针 point 不为空 循环,当为空时,循环结束。
printf("%d",point->date);
point = point->next;
}
putchar('\n');
}
int main()
{
struct Test t1 = {1, NULL};
struct Test t2 = {2, NULL};
struct Test t3 = {3, NULL};
struct Test t4 = {4, NULL};
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
printLink(&t1);
return 0; // 返回 0,表示程序正常结束
}
4.统计链表节点的个数,以及链表查找
#include <stdio.h> // 引入标准输入输出库
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
void printLink(struct Test *head)
{
struct Test *point;
point = head;
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
//计算链表的节点数
int getLink(struct Test *head)
{
int cnt = 0; // 计数器初始化为 0
while(head != NULL) {
cnt++; // 计数器加 1
head = head->next; // 移动到下一个节点
}
return cnt; // 返回链表的节点个数
}
// 链表查找
int searLink(struct Test *head, int date)
{
while(head != NULL) {
if(head->date == date) { // 如果当前节点的 date 等于要查找的 date
return 1; // 返回 1 表示找到
}
head = head->next; // 移动到下一个节点
}
return 0; // 返回 0 表示未找到
}
int main()
{
int i; // 定义一个整数变量 i
int arry[] = {1, 2, 3}; // 定义一个整数数组 arry,并初始化为 1, 2, 3
int len = sizeof(arry) / sizeof(arry[0]); // 计算数组 arry 的长度
for(i = 0; i < len; i++)
{
printf("%d ", arry[i]); // 循环输出数组 arry 的每个元素
}
putchar('\n'); // 输出一个换行符
struct Test t1 = {1, NULL};
struct Test t2 = {2, NULL};
struct Test t3 = {3, NULL};
struct Test t4 = {4, NULL};
t1.next = &t2; // 设置 t1 的 next 指向 t2
t2.next = &t3; // 设置 t2 的 next 指向 t3
t3.next = &t4; // 设置 t3 的 next 指向 t4
printLink(&t1); // 打印链表
int ret = getLink(&t1); // 获取链表长度
printf("%d\n", ret); // 打印链表长度
ret = searLink(&t1, 1); // 查找链表中是否有值为 1 的节点
if(ret == 0) {
printf("no 1\n"); // 如果未找到,输出 "no 1"
} else {
printf("have 1\n"); // 如果找到,输出 "have 1"
}
ret = searLink(&t1, 8); // 查找链表中是否有值为 8 的节点
if(ret == 0) {
printf("no 8\n"); // 如果未找到,输出 "no 8"
} else {
printf("have 8\n"); // 如果找到,输出 "have 8"
}
return 0; // 返回 0,表示程序正常结束
}
5.链表从指定节点后方插入新节点
#include <stdio.h> // 引入标准输入输出库
// 定义结构体 Test
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 从链表的指定日期节点之后插入新节点
int insertFromBehind(struct Test *head, int date, struct Test *new) {
// 定义一个指针p指向链表的头部
struct Test *p = head;
// 遍历链表,直到p为空(即到达链表末尾)
while (p != NULL) {
// 如果找到日期与指定日期匹配的节点
if (p->date == date) {
// 将新节点的next指针指向当前节点的下一个节点
new->next = p->next;
// 将当前节点的next指针指向新节点
p->next = new;
// 插入成功,返回1
return 1;
}
// 移动指针p到下一个节点
p = p->next;
}
// 如果未找到指定日期的节点,返回0
return 0;
}
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head;
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 计算链表的节点数
int getLink(struct Test *head) {
int cnt = 0; // 计数器初始化为 0
struct Test *p = head;
while(p != NULL) {
cnt++; // 计数器加 1
p = p->next; // 移动到下一个节点
}
return cnt; // 返回链表的节点个数
}
// 链表查找
int searLink(struct Test *head, int date) {
while(head != NULL) {
if(head->date == date) { // 如果当前节点的 date 等于要查找的 date
return 1; // 返回 1 表示找到
}
head = head->next; // 移动到下一个节点
}
return 0; // 返回 0 表示未找到
}
// 主函数
int main() {
int i; // 定义一个整数变量 i
int arry[] = {1, 2, 3}; // 定义一个整数数组 arry,并初始化为 1, 2, 3
int len = sizeof(arry) / sizeof(arry[0]); // 计算数组 arry 的长度
// 输出数组 arry 的每个元素
for(i = 0; i < len; i++) {
printf("%d ", arry[i]); // 循环输出数组 arry 的每个元素
}
putchar('\n'); // 输出一个换行符
// 定义四个结构体 Test 并初始化
struct Test t1 = {1, NULL};
struct Test t2 = {2, NULL};
struct Test t3 = {3, NULL};
struct Test t4 = {4, NULL};
// 将这些结构体连接成一个链表
t1.next = &t2;
t2.next = &t3;
t3.next = &t4;
// 定义一个新的结构体节点
struct Test new = {100, NULL};
// 打印链表
printLink(&t1);
puts("----\n");
// 插入新的节点到日期为 4 的节点之后
insertFromBehind(&t1, 4, &new);
// 再次打印链表
printLink(&t1);
return 0;
}
6.1删除头节点,返回链表的头指针
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 删除节点,返回链表的头指针
struct Test* deletNode(struct Test *head, int data)
{
struct Test *p = head; // 初始化指针 p 指向链表的头节点
if(p->date == data) { // 如果头节点的 date 字段与 data 值相等
head = head->next; // 将头节点指向下一个节点
free(p); // 释放原头节点的内存
return head; // 返回新的头节点
}
// 通常还会有更多代码来处理链表中其他节点的删除
return head; // 当前仅处理头节点匹配的情况,返回头节点
}
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head; // 初始化指针 point 指向链表的头节点
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 主函数
int main() {
int i; // 定义一个整数变量 i
int arry[] = {1, 2, 3}; // 定义一个整数数组 arry,并初始化为 1, 2, 3
int len = sizeof(arry) / sizeof(arry[0]); // 计算数组 arry 的长度
// 输出数组 arry 的每个元素
for(i = 0; i < len; i++) {
printf("%d ", arry[i]); // 循环输出数组 arry 的每个元素
}
putchar('\n'); // 输出一个换行符
// 动态分配内存并初始化一个结构体 Test
struct Test *p = (struct Test*)malloc(sizeof(struct Test));
p->date = 1; // 设置 p 的 date 字段为 1
// 定义并初始化其他结构体 Test
struct Test t2 = {2, NULL};
struct Test t3 = {3, NULL};
struct Test t4 = {4, NULL};
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head
// 将这些结构体连接成一个链表
p->next = &t2; // p 的 next 指针指向 t2
t2.next = &t3; // t2 的 next 指针指向 t3
t3.next = &t4; // t3 的 next 指针指向 t4
head = p; // 将 head 指向链表的头节点
// 打印链表
printLink(head);
puts("----\n"); // 输出分隔符
// 删除链表中 date 字段为 1 的节点
head = deletNode(head, 1);
// 再次打印链表
printLink(head);
return 0; // 返回 0 表示程序成功结束
}
6.2删除指定节点
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test
{
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 删除节点,返回链表的头指针
struct Test* deletNode(struct Test *head, int data)
{
struct Test *p = head; // 初始化指针 p 指向链表的头节点
if(p->date == data) { // 如果头节点的 date 字段与 data 值相等
head = head->next; // 将头节点指向下一个节点
free(p); // 释放原头节点的内存
return head; // 返回新的头节点
}
while(p->next != NULL){ // 遍历链表,直到链表末尾
if(p->next->date == data){ // 如果找到节点的 next 的 date 字段与 data 值相等
struct Test* temp = p->next; // 临时保存找到的节点
p->next = p->next->next; // 将当前节点的 next 指针指向找到节点的下一个节点
free(temp); // 释放找到节点的内存
return head; // 返回链表的头节点
}
p = p->next; // 移动到下一个节点
}
return head; // 返回链表的头节点
}
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head; // 初始化指针 point 指向链表的头节点
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 主函数
int main() {
int i; // 定义一个整数变量 i
int arry[] = {1, 2, 3}; // 定义一个整数数组 arry,并初始化为 1, 2, 3
int len = sizeof(arry) / sizeof(arry[0]); // 计算数组 arry 的长度
// 输出数组 arry 的每个元素
for(i = 0; i < len; i++) {
printf("%d ", arry[i]); // 循环输出数组 arry 的每个元素
}
putchar('\n'); // 输出一个换行符
// 动态分配内存并初始化一个结构体 Test
struct Test *p = (struct Test*)malloc(sizeof(struct Test));
p->date = 1; // 设置 p 的 date 字段为 1
// 定义并初始化其他结构体 Test
struct Test t2 = {2, NULL};
struct Test t3 = {3, NULL};
struct Test t4 = {4, NULL};
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head
// 将这些结构体连接成一个链表
p->next = &t2; // p 的 next 指针指向 t2
t2.next = &t3; // t2 的 next 指针指向 t3
t3.next = &t4; // t3 的 next 指针指向 t4
head = p; // 将 head 指向链表的头节点
// 打印链表
printLink(head);
puts("----\n"); // 输出分隔符
// 删除链表中 date 字段为 4 的节点
head = deletNode(head, 4);
// 再次打印链表
printLink(head);
return 0; // 返回 0 表示程序成功结束
}
7.1 通过头插法创建一个链表,并打印出链表中的所有节点。用户需要输入三个整数来创建链表的三个节点。
#include <stdio.h> // 引入标准输入输出库
// 创建动态头插法->指定节点数
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test {
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head; // 初始化指针 point 指向链表的头节点
// 遍历链表
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 从头插法创建链表节点
struct Test* creatFromHead(struct Test *head) {
struct Test *new;
// 为新节点分配内存
new = (struct Test *)malloc(sizeof(struct Test));
printf("请输入新的 NEW\n");
// 读取新节点的 date 值
scanf("%d", &(new->date));
new->next = NULL; // 将新节点的 next 指针设置为 NULL,防止指向野指针
// 如果链表为空,则新节点为头节点
if(head == NULL) {
head = new;
} else {
// 否则,将新节点插入链表头部
new->next = head;
head = new;
}
return head;
}
// 主函数
int main() {
int i = 3;
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head
// 创建指定数量的链表节点
while(i--) {
head = creatFromHead(head);
}
// 打印链表
printLink(head);
return 0; // 返回 0 表示程序成功结束
}
7.2通过头插法创建一个链表,并打印出链表中的所有节点。用户可以输入一系列整数来创建链表,当输入 0 时,链表创建结束。
#include <stdio.h> // 引入标准输入输出库
// 创建动态头插法 —>指定个数,当输入 0 时,链表创建结束
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test {
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head; // 初始化指针 point 指向链表的头节点
// 遍历链表
while(point != NULL) { // 如果当前节点指针 point 不为空则循环,当为空时,循环结束
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 从头插法创建链表
struct Test* creatFromHead(struct Test *head) {
struct Test *new;
while(1) {
// 为新节点分配内存
new = (struct Test *)malloc(sizeof(struct Test));
printf("请输入新的 NEW\n");
// 读取新节点的 date 值
scanf("%d", &(new->date));
new->next = NULL; // 将新节点的 next 指针设置为 NULL,防止指向野指针
// 如果输入的 date 为 0,则退出循环
if(new->date == 0) {
printf("o quit\n");
return head;
}
// 如果链表为空,则新节点为头节点
if(head == NULL) {
head = new;
} else {
// 否则,将新节点插入链表头部
new->next = head;
head = new;
}
}
return head;
}
// 主函数
int main() {
int i = 3;
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head
// 创建链表
head = creatFromHead(head);
// 打印链表
printLink(head);
return 0; // 返回 0 表示程序成功结束
}
注:
1.scanf("%d",&(new->date));为什么要使用取地址符号
- new 是一个指向结构体 Test 的指针:
- struct Test *new
- new = (struct Test *)malloc(sizeof(struct Test));
- new->date 是一个整数变量:
- new->date;
- scanf 需要知道 new->date 变量在内存中的地址,以便将输入的整数存储在 new->date 中:
- scanf("%d", &(new_node->date));
通过 & 运算符,scanf 获得了 new_node->date 的地址,从而可以直接在内存中修改该位置存储的值。
2.new->next = NULL; 的目的是初始化新节点的 next 指针,使其指向 NULL,防止成为野指针。
7.3动态字节前插入数据_函数调用插入新的结构体
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test
{
int date; // 保存日期数据
struct Test *next; // 指向下一个节点的指针
};
// 将新节点插入链表头部的函数
struct Test *inserLink(struct Test *head, struct Test *new_node)
{
if(head == NULL) { // 如果链表为空
head = new_node; // 新节点成为链表的头节点
} else { // 如果链表不为空
new_node->next = head; // 新节点的 next 指向当前的头节点
head = new_node; // 新节点成为新的头节点
}
return head;
}
// 创建链表的函数
struct Test *creatLink(struct Test *head)
{
struct Test *new_node;
while(1) { // 循环创建新节点
new_node = (struct Test *)malloc(sizeof(struct Test)); // 分配新节点的内存
printf("please enter new date\n");
scanf("%d", &(new_node->date)); // 输入新节点的 date
new_node->next = NULL; // 初始化新节点的 next 为 NULL
if(new_node->date == 0) { // 如果输入的 date 为 0,结束输入
printf("over\n");
free(new_node); // 释放新节点的内存
return head; // 返回链表的头节点
}
head = inserLink(head, new_node); // 将新节点插入链表头部
}
}
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point;
point = head;
while(point != NULL) { // 遍历链表
printf("%d ", point->date); // 打印节点的 date
point = point->next; // 移动到下一个节点
}
putchar('\n'); // 换行
}
// 主函数
int main() {
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head,初始化为 NULL
struct Test t1 = {100, NULL}; // 定义一个结构体 Test 实例 t1,并初始化
// 输出分隔符
puts("----\n");
head = creatLink(head); // 创建链表
printLink(head); // 打印链表
head = inserLink(head, &t1); // 将 t1 插入链表头部
printf("Inserted OK\n");
printLink(head); // 打印链表
return 0;
}
8.1通过尾插插法创建一个链表,并打印出链表中的所有节点。
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test {
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point; // 定义一个指向结构体 Test 的指针 point
point = head; // 初始化指针 point 指向链表的头节点
// 遍历链表
while(point != NULL) { // 当当前节点指针 point 不为空时循环
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 将指针 point 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 动态尾插法创建链表
struct Test* creatFromHead(struct Test *head)
{
struct Test *new; // 定义一个指向结构体 Test 的指针 new,用于创建新节点
struct Test *p = head; // 定义一个指向结构体 Test 的指针 p,并将其初始化为链表的头节点
while(1) { // 无限循环,直到遇到 break 结束
new = (struct Test *)malloc(sizeof(struct Test)); // 动态分配新节点的内存空间
printf("please enter new date\n"); // 提示用户输入新节点的 date
scanf("%d", &(new->date)); // 将用户输入的数据存储到新节点的 date 成员中
new->next = NULL; // 初始化新节点的 next 指针为 NULL
if(new->date == 0) { // 如果用户输入的 date 为 0,则表示结束输入
printf("over new date\n"); // 输出提示信息
free(new); // 释放新节点的内存空间
return head; // 返回链表的头指针,结束函数
}
if(head == NULL) { // 如果链表为空
head = new; // 新节点成为链表的头节点
} else { // 如果链表不为空
p = head; // 将指针 p 重新指向链表的头节点
while(p->next != NULL) { // 找到链表的最后一个节点
p = p->next; // 移动指针 p 到下一个节点
}
p->next = new; // 将新节点连接到链表的最后一个节点的 next 指针上
}
}
return head; // 返回链表的头指针(理论上不会执行到这里,因为 while 是无限循环)
}
// 主函数
int main() {
int i = 3; // 定义一个整型变量 i,但未在后续代码中使用
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head,并初始化为 NULL
// 创建链表
head = creatFromHead(head);
// 打印链表
printLink(head);
return 0; // 返回 0 表示程序成功结束
}
else 中的 p=head;
函数的开头已经声明了 struct Test *p = head;,但这个声明只是在第一次while进入循环时有效。当你在循环中遇到 if (head == NULL) 条件并且设置了 head = new; 后,变量 p 没有更新。因此,你需要在 else 分支中重新设置 p = head;,以便在链表非空的情况下从头开始遍历链表。
每次进入循环时,你都需要从链表的头部开始遍历,以便找到链表的末尾位置并将新节点插入到链表的末尾。如果你不在 else 分支中重新设置 p = head;,p 会在第一次插入后保持在链表的尾部,导致后续插入操作无法正确地遍历链表。
else {
p = head; // 将 p 指针重新指向链表的头节点
while(p->next != NULL) { // 遍历链表直到找到最后一个节点
p = p->next;
}
p->next = new; // 将新节点 new 连接到链表的末尾
}
解释:
1. 逻辑背景:
-
- 当链表不为空(即 head != NULL)并且要插入新节点时,需要将新节点插入到链表的末尾。
- p 是一个辅助指针,用来遍历链表找到最后一个节点。
2. 步骤详解:
-
- p = head;:将指针 p 设置为链表的头节点,这样从头开始遍历链表。
- while(p->next != NULL):循环遍历链表,直到找到最后一个节点。条件 p->next != NULL 确保在循环结束时,p 指向链表中最后一个节点。
- p->next = new;:将新节点 new 连接到 p 指向的最后一个节点的 next 指针上,使得新节点成为链表中的新的最后一个节点。
8.2通过尾插插法创建一个链表,并打印出链表中的所有节点。
#include <stdio.h> // 引入标准输入输出库
#include <stdlib.h> // 引入标准库,包含 malloc 和 free 函数
// 定义结构体 Test
struct Test {
int date; // 定义一个整数类型的成员变量 date
struct Test *next; // 定义一个指向结构体 Test 的指针 next
};
// 打印链表中的所有节点
void printLink(struct Test *head) {
struct Test *point; // 定义一个指向结构体 Test 的指针 point
point = head; // 初始化指针 point 指向链表的头节点
// 遍历链表
while(point != NULL) { // 当当前节点指针 point 不为空时循环
printf("%d ", point->date); // 输出当前节点的 date
point = point->next; // 将指针 point 移动到下一个节点
}
putchar('\n'); // 输出换行符
}
// 插入新节点到链表末尾
struct Test *inserLink(struct Test *head, struct Test *new) {
struct Test *p = head; // 定义一个指向结构体 Test 的指针 p,并初始化为链表的头节点
if(p == NULL) { // 如果链表为空
head = new; // 新节点成为链表的头节点
return head; // 返回头节点
}
while(p->next != NULL) { // 找到链表的最后一个节点
p = p->next; // 移动指针 p 到下一个节点
}
p->next = new; // 将新节点连接到链表的最后一个节点的 next 指针上
return head; // 返回头节点
}
// 动态尾插法创建链表
struct Test* creatFromHead(struct Test *head) {
struct Test *new; // 定义一个指向结构体 Test 的指针 new,用于创建新节点
while(1) { // 无限循环,直到遇到 break 结束
new = (struct Test *)malloc(sizeof(struct Test)); // 动态分配新节点的内存空间
printf("please enter new date\n"); // 提示用户输入新节点的 date
scanf("%d", &(new->date)); // 将用户输入的数据存储到新节点的 date 成员中
new->next = NULL; // 初始化新节点的 next 指针为 NULL
if(new->date == 0) { // 如果用户输入的 date 为 0,则表示结束输入
printf("over new date\n"); // 输出提示信息
free(new); // 释放新节点的内存空间
return head; // 返回链表的头指针,结束函数
}
head = inserLink(head, new); // 调用插入函数将新节点插入到链表的末尾
}
return head; // 返回链表的头指针(理论上不会执行到这里,因为 while 是无限循环)
}
// 主函数
int main() {
int i = 3; // 定义一个整型变量 i,但未在后续代码中使用
struct Test *head = NULL; // 定义一个指向结构体 Test 的指针 head,并初始化为 NULL
// 创建链表
head = creatFromHead(head);
// 打印链表
printf("Created linked list:\n");
printLink(head);
// 插入额外节点
struct Test t1 = {100, NULL}; // 创建一个额外的节点 t1
head = inserLink(head, &t1); // 将节点 t1 插入到链表的末尾
printf("After inserting additional node:\n");
printLink(head);
return 0; // 返回 0 表示程序成功结束
}