话不多说先上代码
code
这是一个链表的基本操作,主要功能有链表的添加、删除某个节点、添加某个节点。
#include<stdio.h> // 引入标准输入输出库
#include<stdlib.h> // 引入标准库,用于内存分配等操作
// 定义一个结构体,表示链表的节点
struct node{
int data; // 节点中存储的数据
struct node* next; // 指向下一个节点的指针
};
// 创建一个新的节点
struct node* createnode(int data){
struct node* newnode = (struct node*)malloc(sizeof(struct node)); // 使用malloc分配内存
newnode->data = data; // 设置节点的数据
newnode->next = NULL; // 设置节点的指针为NULL
return newnode; // 返回新创建的节点
}
// 在链表的头部插入一个新节点
void insertnode(struct node** head,int data){
struct node* newnode = createnode(data); // 创建新节点
if(*head == NULL){ // 如果链表为空
*head = newnode; // 将新节点设置为链表的头部
} else {
struct node* temp = *head; // 定义一个临时指针,指向链表的头部
while(temp->next!=NULL){ // 当临时指针的下一个节点不为空时,继续移动临时指针
temp = temp->next;
}
temp->next = newnode; // 将临时指针的下一个节点设置为新节点
}
}
// 打印链表的所有节点数据
void printlist(struct node* head){
while(head != NULL){ // 当链表不为空时
printf("%d ",head->data); // 打印当前节点的数据
head = head->next; // 将头指针移动到下一个节点
}
printf("\n"); // 打印换行符,结束输出
}
// 释放链表所占用的动态内存
void freelist(struct node* head){
struct node* temp;
while(head != NULL){ // 当链表不为空时
temp = head; // 定义一个临时指针,指向链表的头部
head = head->next; // 将头指针移动到下一个节点
free(temp); // 释放临时指针所指向的内存空间
}
}
// 删除指定值的节点
void deletanode(struct node* head,int insertv){
struct node* current = head; // 定义一个指针,指向链表的头部
struct node* prev = NULL; // 定义一个指针,用于保存上一个节点的地址
while(current->data!=insertv&¤t!=NULL){ // 当当前节点的数据不等于要删除的值且当前节点不为空时
prev = current; // 保存当前节点的地址到prev指针中
current = current->next; // 将指针移动到下一个节点
}
if (current != NULL) { // 如果找到了要删除的节点
if (prev == NULL) { // 如果要删除的是头节点
head = current->next; // 将头指针移动到下一个节点,即删除节点后的头节点
} else {
prev->next = current->next; // 将prev指针所指向的节点的下一个节点设置为要删除节点的下一个节点,即删除该节点
}
free(current); // 释放要删除节点的内存空间
}
}
// 插入节点的函数
void insertnode2(struct node* head, int data1, int data2) {
struct node* current = head;
struct node* prev = NULL;
struct node* newnode = createnode(data2); // 创建新节点
while (current != NULL && current->data != data1) {
prev = current;
current = current->next;
}
if (current != NULL) {
if (prev == NULL) {
head = newnode; // 如果要插入的是头节点,更新头节点指针
} else {
prev->next = newnode; // 插入中间节点,更新前一个节点的指针
}
newnode->next = current; // 新节点的指针指向当前节点,完成插入操作
} else {
printf("Node not found.\n"); // 如果找不到指定节点,则输出错误信息
}
}
// 主函数
int main()
{
struct node* head = NULL; // 初始化链表头节点为空
int n, r, f = 1, insertv, newnodev;
printf("请输入你要创建的节点长度:\n");
scanf("%d",&n); // 读取用户输入的节点数量
for(int i = 0; i < n; i++){
int data;
printf("请输入第%d个节点的数据\n",i+1);
scanf("%d",&data); // 读取用户输入的节点数据
insertnode(&head,data); // 插入新节点到链表头部
}
printf("链表数据为:\n");
printlist(head); // 打印链表数据
while(f){
printf("是否有其他操作(1删除节点/2添加节点/输入其他结束)\n");
scanf("%d",&r); // 读取用户选择的操作类型
if(r == 1){ // 如果选择删除节点
printf("请输入要删除的节点值\n");
scanf("%d", &insertv); // 读取用户输入的待删除节点的值
deletanode(head,insertv); // 删除指定节点
printlist(head); // 打印链表数据,确认节点已被删除
}
else if(r == 2){ // 如果选择添加节点
printf("请输入要添加在那个节点以后(节点的值以后)和添加节点的值\n");
scanf("%d%d",&insertv,&newnodev); // 读取用户输入的待插入位置和新的节点值
insertnode2(head,insertv,newnodev); // 在指定位置插入新节点
printlist(head); // 打印链表数据,确认新节点已插入
}
else { // 如果选择结束操作或输入其他数字,则结束循环
break;
}
}
freelist(head); // 释放链表内存空间
return 0; // 程序结束并返回0,表示成功执行
}
操作结果与演示
请输入你要创建的节点长度:
5
请输入第1个节点的数据
1
请输入第2个节点的数据
2
请输入第3个节点的数据
3
请输入第4个节点的数据
4
请输入第5个节点的数据
5
链表数据为:
1 2 3 4 5
是否有其他操作(1删除节点/2添加节点/输入其他结束)
1
请输入要删除的节点值
3
1 2 4 5
是否有其他操作(1删除节点/2添加节点/输入其他结束)
2
请输入要添加在那个节点以后(节点的值以后)和添加节点的值
4 3
1 2 3 4 5
是否有其他操作(1删除节点/2添加节点/输入其他结束)
3
Process returned 0 (0x0) execution time : 16.983 s
Press any key to continue.
每个函数功能的解释与实现
结构体
struct node{//定义结构体
int data;//存结构点的值
struct node* next;//指针方便指向下一个节点
};
head节点、设置下一个节点节点
create/创造 data/数据
// 定义一个创建节点的函数,接受要存储的数据
struct node* createnode(int data){
// 分配动态内存以存储节点结构体
struct node* newnode = (struct node*)malloc(sizeof(struct node));
// 将传入的data存储到新节点的data成员中
newnode->data = data;
// 将新节点的next指针初始化为NULL
newnode->next = NULL;
// 返回新节点的地址
return newnode;
}
在最后一位增加一个节点
insert/插入、嵌入 这个函数用于创建一个新的链表节点,并为该节点分配动态内存。新节点的数据成员被设置为传入的data参数,而next指针被初始化为NULL。最后,函数返回新节点的地址,以便在其他函数中使用。
// 定义一个插入节点的函数,接受链表头指针的地址和要插入的数据
void insertnode(struct node** head, int data){
// 创建一个新节点,并将数据放入节点
struct node* newnode = createnode(data);
// 如果链表为空,即头节点为NULL
if(*head == NULL){
// 将新节点的地址赋给头指针,即设置头节点
*head = newnode;
} else {
// 定义一个临时指针,指向链表的头节点
struct node* temp = *head;
// 遍历链表,直到找到最后一个节点(即next指针为NULL的节点)
while(temp->next!=NULL){
// 将临时指针移动到下一个节点
temp = temp->next;
}
// 将最后一个节点的next指针指向新节点,完成插入操作
temp->next = newnode;
}
}
输出
这个函数通过遍历链表,逐个打印每个节点的数据。当遍历到链表的末尾(即头节点为NULL)时,循环结束。最后,打印一个换行符,使输出结果更整齐。
// 定义一个打印链表的函数,接受链表的头节点
void printlist(struct node* head){
// 当头节点不为NULL时,继续循环
while(head != NULL){
// 打印当前节点的数据
printf("%d ",head->data);
// 将头节点更新为下一个节点
head = head->next;
}
// 打印换行符,使输出更整齐
printf("\n");
}
释放内存
这个函数通过遍历链表,逐个释放每个节点所占用的动态内存。在释放当前节点内存之前,需要先将头节点更新为下一个节点,以免在释放内存后访问已经无效的内存区域。最后,当遍历到链表的末尾时,循环结束。
// 定义一个释放链表的函数,接受链表的头节点
void freelist(struct node* head){
// 定义一个临时指针,用于遍历链表
struct node* temp;
// 当头节点不为NULL时,继续循环
while(head != NULL){
// 将临时指针指向当前节点
temp = head;
// 将头节点更新为下一个节点
head = head->next;
// 释放当前节点所占用的动态内存
free(temp);
}
}
删除节点
这个函数通过遍历链表,查找并删除指定数据的节点。如果找到了要删除的节点,它会更新链表中的链接以删除该节点,并释放该节点所占用的动态内存。
// 定义一个删除节点的函数,接受链表的头节点和要删除的数据
void deletanode(struct node* head, int insertv) {
// 定义一个指针,指向链表的头节点
struct node* current = head;
// 定义一个指针,用于保存上一个节点的地址
struct node* prev = NULL;
// 遍历链表,查找要删除的节点
while(current->data != insertv && current != NULL) {
// 如果当前节点不是要删除的节点,则保存当前节点的地址
prev = current;
// 将指针移动到下一个节点
current = current->next;
}
// 如果找到了要删除的节点
if (current != NULL) {
// 如果上一个节点是头节点,则将头节点更新为下一个节点
if (prev == NULL) {
head = current->next;
// 否则,将上一个节点的next指针更新为要删除节点的下一个节点
} else {
prev->next = current->next;
}
// 释放要删除节点的动态内存
free(current);
}
}
插入
这个函数的功能是在链表中查找特定数据的位置,并在该位置插入一个新的节点。如果找到了要插入的位置,它会更新链表中的链接以插入新节点。如果找不到指定节点,则输出错误信息。
// 定义一个插入节点的函数,接受链表的头节点和要插入的数据
void insertnode2(struct node* head, int data1, int data2) {
// 定义一个指针,指向链表的头节点
struct node* current = head;
// 定义一个指针,用于保存上一个节点的地址
struct node* prev = NULL;
// 创建一个新节点,并存储数据data2
struct node* newnode = createnode(data2); // 创建新节点
// 遍历链表,查找要插入的位置
while (current != NULL && current->data != data1) {
// 如果当前节点不是要插入的位置,则保存当前节点的地址
prev = current;
// 将指针移动到下一个节点
current = current->next;
}
// 如果找到了要插入的位置
if (current != NULL) {
// 如果要插入的是头节点,更新头节点指针
if (prev == NULL) {
head = newnode; // 如果要插入的是头节点,更新头节点指针
// 否则,将上一个节点的next指针更新为要插入节点的next指针
} else {
prev->next = newnode; // 插入中间节点,更新前一个节点的指针
}
// 新节点的next指针指向当前节点,完成插入操作
newnode->next = current; // 新节点的指针指向当前节点,完成插入操作
} else {
// 如果找不到指定节点,则输出错误信息
printf("Node not found.\n"); // 如果找不到指定节点,则输出错误信息
}
}
主函数
这个程序通过定义一个链表结构和一个主函数来执行一系列的操作。它首先要求用户输入要创建的节点数量,然后循环n次来创建这些节点并插入到链表的头部。接下来,它打印链表的所有节点数据。然后它进入一个循环,等待用户选择操作。用户可以选择删除一个节点或添加一个新节点到链表的指定位置。最后,它释放链表所占用的动态内存并结束程序。
int main() // 主函数开始
{
struct node* head = NULL; // 定义一个指向链表头节点的指针,初始化为NULL
int n, r, f = 1, insertv, newnodev; // 定义多个变量,包括节点数量n、操作选择r、循环标志f以及两个用于插入和删除节点的值
printf("请输入你要创建的节点长度:\n"); // 提示用户输入要创建的节点数量
scanf("%d",&n); // 从标准输入读取节点数量
for(int i = 0; i < n; i++){ // 循环n次,每次创建一个新节点并输入数据
int data;
printf("请输入第%d个节点的数据\n",i+1); // 提示用户输入当前节点的数据
scanf("%d",&data); // 从标准输入读取节点数据
insertnode(&head,data); // 调用insertnode函数,将新节点插入到链表的头部
}
printf("链表数据为:\n"); // 打印提示信息
printlist(head); // 调用printlist函数,打印链表的所有节点数据
while(f){ // 当f为1时,进入循环,等待用户选择操作
printf("是否有其他操作(1删除节点/2添加节点/输入其他结束)\n"); // 提示用户选择操作
scanf("%d",&r); // 从标准输入读取用户的选择
if(r == 1){ // 如果用户选择删除节点
printf("请输入要删除的节点值\n"); // 提示用户输入要删除的节点的值
scanf("%d", &insertv); // 从标准输入读取要删除的节点的值
deletanode(head,insertv); // 调用deletanode函数,删除指定值的节点
printlist(head); // 打印链表的所有节点数据,以确认删除操作
}
else if(r == 2){ // 如果用户选择添加节点
printf("请输入要添加在那个节点以后(节点的值以后)和添加节点的值\n"); // 提示用户输入要插入的位置和要插入的数据
scanf("%d%d",&insertv,&newnodev); // 从标准输入读取位置和数据
insertnode2(head,insertv,newnodev); // 调用insertnode2函数,在指定位置插入新节点
printlist(head); // 打印链表的所有节点数据,以确认插入操作
}
else
break; // 如果用户选择结束操作,跳出循环
}
freelist(head); // 调用freelist函数,释放链表所占用的动态内存
return 0; // 主函数返回0,表示程序正常结束
}