动态单向链表的增删改查

ops/2024/10/18 19:24:52/

学习建议:

1、看完一节视频,立即去实践,随学随练。

2、优秀的视频比自己去看书,更能消化理解

3、学习效果的检验方法是独立实现功能,实现后对比视频中的教学代码,查漏补缺。

4、独立编写过程中记录。

教学视频:https://www.bilibili.com/video/BV1yv411y7AW?p=5&vd_source=da60f9e1bc3321cae28c29fe80e9b078

REAME 如下:

2024/04/30
-目标:独立实现动态单向链表的增删改查
-编译方式:gcc -g link_list.c迭代如下:
版本1:link_list.c-v0.1:step1.[链表初始化],也就是创建链表,也就是创建一个头节点,并且使 next = NULL;注意:初始化函数不需要形参(和大多数初始化函数一样),只需要返回值是一个指针即可。step2.链表节点的增加,也就是链表节点的插入。-[尾插法]:借助尾指针prear 该指针始终指向尾节点。存在问题:函数设计的参数列表设计有问题。-头插法:待增加。step3.[链表的遍历]。借助辅助指针 current。-存在的问题:尾节点的数据未打印出来。解决:正确的循环条件是 while(current != NULL)版本2:
link_list.c-v0.2:step1.继续完成使用[头插法完成在某个节点前面插入新节点]。-使用两个辅助指针pre、current, 同时移动两个指针。-初始时,pre指向头节点, current 指向头节点的下一个节点。存在的问题:1、注意while 循环的条件; 查找到数据后应退出循环2、需要考虑没有找到带查找节点。step2.[清空链表],只保留头节点。记录释放节点的下一个节点。-存在问题: 别忘了最后要把头节点指向NULL。step3.[删除某节点] 修改指向; 释放空间注意: 释放空间后,需要将该指针变量指向NULL。step4.[销毁链表],头节点都释放了。存在的问题: 销毁链表后进行遍历链表,遍历出来的头节点的数据是随机值,不正常,因此将销毁链表函数的形参修改为了二级指针。存在的问题:
-1、看教学视频中老师是先在.h 文件中先声明函数,然后再在.c 文件中编写函数。而我只在.h 文件中声明了一个结构体,然后只顾着在.c 文件中写函数了。参考连接:https://www.bilibili.com/video/BV1yv411y7AW?p=5&vd_source=da60f9e1bc3321cae28c29fe80e9b078

头文件:link_list.h

typedef struct _link_node{int value;struct _link_node* next;
}link_node;

源文件:版本1:link_list.c-v0.1

#include <stdio.h>
#include <stdlib.h>
#include "link_list.h"/*链表的遍历*/
void traverse_link_list(link_node* phead)
{link_node* current = phead;if(phead->next == NULL)printf("link list is null!\n");while(current != NULL){printf("%d\n", current->value);current = current -> next;}   
}/*链表的插入-尾插法*/
void tail_insert_link_list(link_node* current, link_node** rear, int value)
{link_node* new = NULL;new = (link_node*)malloc(sizeof(link_node));new->value = value;new->next = NULL;current->next = new;rear = &new;
}/*链表初始化*/
link_node* init_link_list()
{link_node* node = (link_node*)malloc(sizeof(link_node));node -> next = NULL;node -> value = -1;return node;
}int main()
{link_node* phead;link_node* rear = NULL;link_node* current;/*链表初始化*/ phead = init_link_list();int i = 0;current = phead; /*使用尾插法填充链表*/for(i = 1; i < 6; i++){tail_insert_link_list(current, &rear, i);current = current -> next;}/*遍历链表*/ traverse_link_list(phead);   return 0; 
}

版本2:link_list.c-v0.2

#include <stdio.h>
#include <stdlib.h>
#include "link_list.h"/*销毁链表*/
void destory_link_list(link_node** phead)
{if(*phead == NULL)return;link_node* current = *phead;link_node* pnext;while(current != NULL){pnext = current->next;free(current);current = pnext;   }*phead = NULL;   
}/*删除某节点*/
void remove_node(link_node* phead, int value)
{if(phead == NULL)return;link_node* pre = phead;link_node* current = pre->next;while(current != NULL){if(current->value == value)break;pre = current;current = current->next;   }/*没找到*/if(current == NULL)return;    pre->next = current->next;free(current);current = NULL;/*释放后仍要让该指针变量指向NULL*/   
}/*清空链表*/
void clean_link_list(link_node* phead)
{if(phead == NULL)return;link_node* current = phead->next;link_node* pnext;while(current != NULL){pnext = current->next;  /*先记录当前节点的下一个节点*/printf("%d ", current->value);   free(current);          /*释放当前节点*/current = pnext;        /*让current指向下一节点*/}/*别忘了最后要将头节点指向NULL*/ phead->next = NULL; printf("节点已被删除\n");
}/*插入节点-在某节点前插入新节点*/
void head_insert_link_list(link_node* phead, int cur_value, int new_value)
{if(phead == NULL){   return;}link_node* pre = phead;link_node* current = pre->next;link_node* new = NULL;/*1.查找某节点*/while(current != NULL){/*查找到节点后应立即退出循环*/if(current->value == cur_value)break;pre = current;  /*记录节点*/current = current->next;   }#if 0/*注释掉该代码块,没找到节点,会将新节点追加在尾节点的后面*/    /*没有查找到节点立即退出*/if(current == NULL)return;
#endif    /*2.插入新节点*/new = (link_node*)malloc(sizeof(link_node));new->value = new_value;/*特别注意:下面的顺序不能颠倒*/ new->next = current;pre->next = new;
}/*链表的遍历*/
void traverse_link_list(link_node* phead)
{if(phead == NULL){printf("该链表可能已经被销毁!\n");return;}link_node* current = phead;if(phead->next == NULL)printf("link list is null!\n");while(current != NULL){printf("%d\n", current->value);current = current -> next;}   
}/*链表的插入-尾插法*/
void tail_insert_link_list(link_node* current, link_node** rear, int value)
{link_node* new = NULL;new = (link_node*)malloc(sizeof(link_node));new->value = value;new->next = NULL;current->next = new;rear = &new;
}/*链表初始化*/
link_node* init_link_list()
{link_node* node = (link_node*)malloc(sizeof(link_node));node -> next = NULL;node -> value = -1;return node;
}int main()
{link_node* phead;link_node* rear = NULL;link_node* current;/*链表初始化*/ phead = init_link_list();int i = 0;current = phead; /*使用尾插法填充链表*/for(i = 1; i < 6; i++){tail_insert_link_list(current, &rear, i);current = current -> next;}/*遍历链表*/ traverse_link_list(phead);printf("链表填充完毕!\n");/*在某节点前插入新节点*/ head_insert_link_list(phead, 10, 0);traverse_link_list(phead);/*删除某节点*/remove_node(phead, 3);printf("已删除节点!\n");traverse_link_list(phead);/*清空链表*/clean_link_list(phead);printf("已清空链表!\n");traverse_link_list(phead); /*销毁链表*/destory_link_list(&phead);traverse_link_list(phead);   return 0; 
}


http://www.ppmy.cn/ops/26200.html

相关文章

R语言的学习——day1

将数据框中某一列数据改成行名 代码 结果

DSP开发实战教程--EPWM模块的影子寄存器详细讲解原理和代码实例

EPWM模块影子寄存器的原理 在TI&#xff08;Texas Instruments&#xff09;的DSP28335中&#xff0c;EPWM&#xff08;Enhanced Pulse Width Modulator&#xff09;模块提供了高精度、高灵活性的PWM信号生成功能。为了能在不影响当前PWM波形输出的情况下预装载新的PWM参数&…

REACT: SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS【大模型的协同推理】

目录 前言一、ABSTRACT二、INTRODUCTION三、KNOWLEDGE-INTENSIVE REASONING TASKS3-1、SETUP3-2、METHODS3-3、RESULTS AND OBSERVATIONS 四、DECISION MAKING TASKS4-1、ALFWorld TASK4-2、WebShop TASK 五、RELATED WORK六、CONCLUSION总结 前言 文章提出了ReAct方法&#xf…

LVGL自定义滑动

触摸和编码器都可以操作 typedef struct {lv_obj_t* obj;int16_t x;int16_t y;int16_t width;int16_t height; }pos_and_size_t;typedef struct {lv_obj_t* obj;lv_coord_t height;lv_coord_t width;lv_coord_t width_pad;lv_coord_t height_pad;lv_coord_t child_widget;lv_co…

Linux 查看所有进程 ps -ef 命令详解, 查看网络链接信息 netstat -tuplan 命令详解

ps -ef 指令 在Linux系统中&#xff0c;ps 是一个非常基础且强大的命令行工具&#xff0c;用于报告当前系统中运行的进程的状态。它是 “Process Status” 的缩写。通过使用不同的选项和参数&#xff0c;ps 命令能够以多种格式展示进程信息&#xff0c;帮助用户了解系统中进程…

Linux IP Forwarding路由转发实验

linux 路由转发功能 Linux 操作系统具备路由转发功能&#xff0c;路由功能是指 Linux 操作系统提供的路由管理和转发功能&#xff0c;它允许 Linux 主机在网络中正确地转发数据包&#xff0c;并确保数据包能够达到其目的地。 出于安全考虑&#xff0c;Linux系统默认是禁止数据…

【Flutter】极光推送配置流程(小米厂商通道) 章二

前言 继【Flutter】极光推送配置流程(极光通道/华为厂商/IOS) 章一 并且&#xff0c;我大概率不会去修改第一篇文章的内容。 随着我自己在配置公司的项目的同时&#xff0c;我希望一直更新这个推送系列文章。 在章一配置完后&#xff0c;也是出现了一些问题&#xff0c;所以本…

Flask 3 保姆级教程(一):快速上手

一、创建项目 PyCharm 中新建项目 创建完成后会出现这么个项目 以下是代码解析&#xff1a; # 导入了 Flask 类 from flask import Flask# 创建了一个 Flask web 应用的实例&#xff0c;并将其赋值给变量 app # __name__ 是一个特殊的 Python 变量&#xff0c;它表示当前模块…