因为博主认为单链表是非常重要的数据结构,能够熟练使用单链表的话后面的数据结构会越学越轻松,所以博主就把这篇博客做的细致一点,不是很好懂的地方做成 gif 动画,希望大家能理解期中代码的含义

学习链表的最好方法:

画图,必须是自己画图

下面给出博主的代码,相信大家仔细看的话是能看懂的.
部分细节在做 gif 时顾及不到,不要见怪了,主要是思想

#include<stdlib.h>
#include<stdio.h>typedef struct _LinkList {int data;  //数据域struct _LinkList *next;    //指针域int length;    //用来描述单链表中的元素的个数
}LinkList, LinkNode;
// 实现单链表的构建、数据添加(头插法和尾插法)、数据删除(包含了数据查找),数据的修改(包含了数据查找)、遍历的算法设计;//单链表的初始化
bool initList(LinkList *Lq) {Lq->next = NULL;   //让指针域指向空,为了防止以外的错误if (!Lq) return false;Lq->data = -93501122;      //初始化头结点的数据域,Lq->length = 0;return true;
}//显示页面
void menue() {printf("****************************************************************\n");printf("*********请选择你要进入的模块*********\n");printf("**1.使用头插法添加元素(最后输出的顺序与输入的顺序是相反的!**\n");printf("-----------------------------------\n");printf("**2.使用尾插法添加元素(最后输出的顺序与输入的顺序是相同的!**\n");printf("-----------------------------------\n");printf("**3.删除单链表中的元素\n");printf("-----------------------------------\n");printf("**4.修改单链表中的元素\n");printf("-----------------------------------\n");printf("**5.清屏,在现实欢迎界面\n");printf("-----------------------------------\n");printf("**0.退出程序");printf("****************************************************************\n\n\n");
}
//单链表的数据添加--->头插法
bool addList_font(LinkList *Lq, LinkNode *node) {if (!node) return false;   //如果之前的 node 分配地址失败的话,直接返回node->next = Lq->next;Lq->next = node;Lq->length++;return true;
}//单链表的数据添加--->尾插法
bool addList_last(LinkList *Lq, LinkNode *node) {if (!node) return false;   //表示在分配给 node 空间的时候分配失败,那么我们后续的代码也就没了执行的必要LinkList *last = Lq; //用来执行我们最后一个元素while (last->next) last = last->next;node->next = NULL;last->next = node;Lq->length++;return true;}//遍历
void Pint_add(LinkList *Lq) {LinkList *temp = Lq->next;printf("现在单链表一共有 %d 个元素,它们依次是: ",Lq->length);while (temp) {printf("%d ", temp->data);temp = temp->next;}printf("\n");return;
}
//数据删除,先进行查找,如果找到要删除的元素就进行删除并且返回被删除的元素是第几个元素
bool list_del(LinkList *Lq, int element, int *index) {LinkNode *temp, *sq;  //temp是用来查询的 sq是用来删除的int i = 0;temp = Lq;sq = temp->next;if (Lq->next == NULL) return false;//如果链表里只有一个头结点,那么我们就直接返回while (sq) { //当跳出循环时,要么没有找到我们要删除的元素,要么就是已经删除了我们要删除的元素返回了。if (sq->data == element && sq->next != NULL) {//当找到了要删除的元素而且该元素不是最后一个元素temp->next = sq->next;*index = i;Lq->length--;free(sq);sq->next = NULL;return true;} else if (sq->data == element && sq->next == NULL) {//找到了要删除的元素,并且该元素是最后一个元素temp->next = NULL;*index = i;Lq->length--;free(sq);sq->next = NULL;return true;} else {//在循环的时候没有找到,所以我们继续寻找temp = temp->next;sq = sq->next;i++;}}return false;
}
//数据修改
bool mov_del(LinkList *Lq, int oldelement,int newelement, int *index) {LinkList *temp;temp = Lq->next;  //让temp指向第一个节点while (temp) {    //当跳出循环时,要么是成功修改了要修改的值,返回是单链表的第几个元素,要么是没找到要修改的值if (temp->data == oldelement) {//找到了我们就修改它temp->data = newelement;return true;} else {//没找到,temp指向下一个节点再次寻找temp = temp->next;}}return false;
}
int main(void) {//单链表的创建LinkList *Lq = (LinkList*)malloc(sizeof(LinkList));    //给最初的 头结点分配一份空间LinkNode *node = NULL;int num=0;  //添加或删除元素的个数int element = 0;//删除元素的值,要修改元素的值int index=0;  //用来提示被删除元素是第几个元素,或者提示要被修改了的元素是第几个元素。int newelement = 0;   //要修称为的新值int choice = 0;   //用来选择进入那个模块//单链表的初始化if (initList(Lq)) {printf("单链表初始化成功!\n");} else {printf("单链表初始化失败!\n");}menue();while (1) {printf("请输入你想要进入的模块: ");scanf("%d", &choice);if (choice > 5 || choice < 0) {  //判断用户的输入是否合法,如果输入不合法,那么就提示用户重新输入。printf("输入的值不合法!  请重新选择\n");continue;}switch (choice) { //进入我们对应的分支语句case 0:    //退出本程序return 0;case 1://数据添加--->头插法printf("欢迎使用 头插法插入元素!! 请输入你想要添加的元素个数:  ");scanf("%d", &num);for (int i = 0; i < num; i++) {node = (LinkNode*)malloc(sizeof(LinkNode));    //给我们要写入的结点分配空间这样才能把我们要添加的元素连接上去printf("请输入你要添加的元素的值: ");scanf("%d", &node->data);if (addList_font(Lq, node)) {  //进入子函数printf("添加元素 %d 成功\n", node->data);} else {printf("添加元素失败!\n");}}Pint_add(Lq);    //遍历break;case 2://数据添加--->尾插法printf("欢迎使用 尾插法插入元素!!     请输入你想要添加的元素个数:  ");scanf("%d", &num);for (int i = 0; i < num; i++) {node = (LinkNode*)malloc(sizeof(LinkNode));//给我们要写入的结点分配空间这样才能把我们要添加的元素连接上去printf("请输入你要添加的元素的值: ");scanf("%d", &node->data);if (addList_last(Lq, node)) {    //进入子函数printf("添加元素 %d 成功\n", node->data);} else {printf("添加元素失败!\n");}}Pint_add(Lq);    //遍历break;case 3://数据删除,先进行查找,如果找到要删除的元素就进行删除并且返回被删除的元素是第几个元素printf("请输入你想要删除的元素: ");scanf("%d", &element);if (list_del(Lq, element, &index)) { //进入子函数,传入的参数依次是 单链表 要删除的元素 索引值printf("删除元素成功,该元素在单链表中是第 %d 个元素:\n ", index + 1);} else {printf("删除失败,单链表里没有该元素! \n");}Pint_add(Lq);break;case 4://数据修改index = 0; //先将我们的索引值置空printf("请输入你想要修改的元素: ");scanf("%d", &element);printf("请输入你想要修改称为的值: ");scanf("%d", &newelement);if (mov_del(Lq, element, newelement, &index)) { //进入子函数进行修改我们的单链表的值printf("修改元素成功,该元素在单链表中是第 %d 个元素:\n ", index);} else {printf("修改失败,单链表里没有该元素! \n");}Pint_add(Lq);break;case 5:system("cls");   //将屏幕清空 menue();    //显示欢迎界面,方便用户操作Pint_add(Lq);    //显示现在单链表内的元素,方便用户观看break;}}//释放资源free(Lq);free(node);Lq = NULL;node = NULL;system("pause");return 0;
}

如果看完代码感觉还是不好的话,可以观看博主做的 gif (可能不是很标准,但是博主就是这样理解的)

插入(头插法)

我们插入3个数 1 2 3

bool addList_font(LinkList *Lq, LinkNode *node) {if (!node) return false;    //如果之前的 node 分配地址失败的话,直接返回node->next = Lq->next;Lq->next = node;Lq->length++;return true;
}

插入1

插入2:

插入3:


所以大家能理解为什么使用 头插法 遍历出来的顺序是与我们输入的顺序相反的了吧。

插入(尾插法)

我们插入3个数 1 2 3

bool addList_last(LinkList *Lq, LinkNode *node) {if (!node) return false;    //表示在分配给 node 空间的时候分配失败,那么我们后续的代码也就没了执行的必要LinkList *last = Lq; //用来执行我们最后一个元素while (last->next) last = last->next;node->next = NULL;last->next = node;Lq->length++;return true;}

插入 1:

插入2:

插入3:

删除

删除我们也分为两个部分

  • 删除的元素是最后一个元素
  • 删除的元素不是最后一个元素
![bool list_del(LinkList *Lq, int element, int *index) {LinkNode *temp, *sq; //temp是用来查询的 sq是用来删除的int i = 0;temp = Lq;sq = temp->next;if (Lq->next == NULL) return false;//如果链表里只有一个头结点,那么我们就直接返回while (sq) { //当跳出循环时,要么没有找到我们要删除的元素,要么就是已经删除了我们要删除的元素返回了。if (sq->data == element && sq->next != NULL) {//当找到了要删除的元素而且该元素不是最后一个元素temp->next = sq->next;*index = i;Lq->length--;free(sq);sq->next = NULL;return true;} else if (sq->data == element && sq->next == NULL) {//找到了要删除的元素,并且该元素是最后一个元素temp->next = NULL;*index = i;Lq->length--;free(sq);sq->next = NULL;return true;} else {//在循环的时候没有找到,所以我们继续寻找temp = temp->next;sq = sq->next;i++;}}return false;
}

删除的元素是最后一个元素(太大了只能上传较差的,要看完整的请看我的百度网盘):

删除的元素不是最后一个元素:

修改

bool mov_del(LinkList *Lq, int oldelement,int newelement, int *index) {LinkList *temp;temp = Lq->next;   //让temp指向第一个节点while (temp) {    //当跳出循环时,要么是成功修改了要修改的值,返回是单链表的第几个元素,要么是没找到要修改的值if (temp->data == oldelement) {//找到了我们就修改它temp->data = newelement;return true;} else {//没找到,temp指向下一个节点再次寻找temp = temp->next;}}return false;
}

修改比较简单就做一个就行了:

因为 gif 上传大小有限制,所以想看完整的视频可以点击我的百度网盘进行观看
希望大家能掌握单链表
如果觉得博主做的博客有用的话别忘了点赞加评论哦

数据结构与算法 完整版单链表(附GIF)相关推荐

  1. 数据结构与算法 完整版双链表

    上一篇单链表博主已经讲的很详细了,相信掌握单链表的朋友搞定双链表并不困难,所以博主就之给出代码了,如果实在感觉理解困难可以留言,博主会加gif的 #include<stdio.h> #in ...

  2. 【python】数据结构和算法 + 浅谈单链表与双链表的区别

    有这么一句话说"程序=数据结构+算法",也有人说"如果把编程比作做菜,那么数据结构就好比食材(菜),算法就好比厨艺(做菜的技巧)". 当然这是笼统的说法,不过也 ...

  3. 【数据结构与算法】判断单链表是否有环的算法

    带环链表 这里的带环单链表可不是环形单链表,这个环可能是我们不想要的,所以需要检测. 我们就不假设有一个打结状的环了,那样跑到哪里去也不清楚,这里的"带环链表",环必然是在末端. ...

  4. 数据结构与算法-python描述-单链表

    # coding:utf-8# 单链表的相关操作: # is_empty() 链表是否为空 # length() 链表长度 # travel() 遍历整个链表 # add(item) 链表头部添加元素 ...

  5. (数据结构)1.实现顺序表的各种基本运算的算法 2.实现单链表的各种基本运算的算法

    实验内容 1.编写一个程序sqlist.cpp,实现顺序表的各种基本运算和整体建表算法(假设顺序表的元素类型ElemType为char),并在此基础上设计一个程序exp2-1.cpp完成以下功能. ( ...

  6. TypeScript算法专题 - blog5 - 单链表节点的`任意k个分组反转`的实现

    TypeScript数据结构与算法专题 - [单链表5] 单链表节点的`任意分组反转`实现 李俊才 CSDN:jcLee95 邮箱:291148484@163.com 专题目录:https://blo ...

  7. 数据结构与算法之线性结构链表

    数据结构与算法之线性结构链表 这一篇文章主要介绍的是通过java实现单链表.循环链表和双向循环链表,仅供自己复习使用,如有什么不足之处,欢迎指出. 单链表: package xianxingjiego ...

  8. 数据结构与算法(C++)– 链表(Link)

    数据结构与算法(C++)– 链表(Link) 1.基础知识 表:把具有相同类型的序列 A0, A1, A2, - An 称为表 .n 是表的大小,n=0 称为空表. A0没有前驱,An没有后继. 前驱 ...

  9. 数据结构与算法之反转单向链表和双向链表

    数据结构与算法之反转单向链表和双向链表 目录 反转单向链表和双向链表 1. 反转单向链表和双向链表 题目描述 代码实现 public class Code_ReverseList {public st ...

最新文章

  1. Linux学习笔记-题记
  2. python如何爬虫网页数据-python网络爬虫爬取网页内容
  3. 通过Maven去运行单元测试
  4. Linux环境下安装Python第三方库
  5. [Mvp.Blazor] 集成Ids4,实现统一授权认证
  6. GC基本算法及C++GC机制
  7. Java停止线程的方式
  8. 托管非托管_如何利用Kubernetes的力量来优化您的托管成本
  9. 散射回波仿真Matlab,基于matlab的体目标回波模拟方法与流程
  10. 易班自动答题脚本_Python实现手机APP之自动打卡签到详细教程(小白合适)
  11. dev万能头文件_超级好用的C++万能头文件
  12. SCI 论文缩写使用心得
  13. 窗户控制app开发day1(机智云的二次开发之换皮肤)
  14. 类模板 Class Templates
  15. 20款优秀的数据可视化工具 (建议收藏)
  16. Android手机开发者模式
  17. 4G DTU和4G工业路由器有哪些区别?
  18. layuiAdmin 框架单页面文档
  19. java电信计费项目论文_电信计费系统的设计与实现毕业论文.doc
  20. 本地域名配置:hosts文件的位置和作用

热门文章

  1. Ubuntu 17安装Virtual Box
  2. Flutter基础—手势处理
  3. 等离子切割机行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
  4. 文件没有后缀名,如何批量添加为.jpg
  5. SQL注入学习part03:(结合sqli-libs学习:21-30关)
  6. 机器学习:理解逻辑回归及二分类、多分类代码实践
  7. 拿到人工智能offer,一个腾讯,一个阿里,选哪个?
  8. 董明珠今晚开启抖音直播首秀;传苹果将去掉 iPhone 闪电接口;PyTorch 1.5 发布 | 极客头条...
  9. 华为面向全球发布HMS Core 4.0意味着什么?
  10. “瘟疫”笼罩下的物联网危与机