五大板块(4)——链表

参考:五大板块(4)——链表
作者:丶PURSUING
发布时间: 2021-02-15 09:33:29
网址:https://blog.csdn.net/weixin_44742824/article/details/114981905

目录

  • 一、对比链表与数组
    • 同样是存放一串数据,链表与数组的区别在哪里?
    • 链表方便增删
  • 二、链表的静态创建
    • 链表的动态遍历:统计节点个数与查找节点
  • 三、插入节点与删除节点
    • 从指定节点的后方插入新节点
    • 在指定节点前方插入新节点
    • 删除指定节点
  • 四、链表的动态创建
    • 头插法创建链表
    • 尾插法创建链表

一、对比链表与数组

同样是存放一串数据,链表与数组的区别在哪里?

在这里插入图片描述

数组是申请连续的地址存放数据,在增加或删除某一元素不方便。

而链表可以很好地解决这个问题。

链表方便增删

大致思路:

  • 增加节点

在这里插入图片描述

  • 删除节点
    在这里插入图片描述

二、链表的静态创建

#include <stdio.h>struct Test
{int data;struct Test *next;
};int main()
{struct Test t1 ={1,NULL};struct Test t2 ={2,NULL};struct Test t3 ={3,NULL};t1.next = &t2;//t1的指针指向了t2的地址t2.next = &t3;//t1.next是一个结构体指针,访问里面的data自然要用->printf("%d %d %d\n",t1.data,t1.next->data,t1.next->next->data);return 0;
}

链表的动态遍历:统计节点个数与查找节点

#include <stdio.h>struct Test
{int data;struct Test *next;
};//遍历链表,把节点数据打印出来
void printLink(struct Test *head)
{int i;struct Test *p = head;while(p != NULL){printf("%d ",p->data);p = p->next;}
}
//统计链表节点个数
void getNodeNum(struct Test *head)
{int cnt = 0;struct Test *p = head;while(p != NULL){cnt++;p = p->next;}printf("链表节点的个数是:%d\n",cnt);
}//找节点
void findNode(struct Test *head,int data)
{struct Test *p = head;while(p != NULL){if(p->data == data){printf("找到了\n");return;//直接退出子函数,返回main函数}p = p->next;}printf("没找到\n");
}int main()
{struct Test t1 ={1,NULL};struct Test t2 ={2,NULL};struct Test t3 ={3,NULL};t1.next = &t2;//t1的指针指向了t2的地址t2.next = &t3;printLink(&t1);getNodeNum(&t1);findNode(&t1,2);return 0;
}

结果:

1 2 3 链表节点的个数是:3
找到了
  • 1
  • 2

要重点理解的是:p = p->next
指针p指向了下一个结构体的地址,p->next中存放的正是下一个链表节点的地址。
p本身是一个结构体指针,所以用->访问成员next.

三、插入节点与删除节点

从指定节点的后方插入新节点

思路:
(1)找到指定节点
(2)把指定节点的的next指向new节点的地址
(3)new节点的next指向下一个节点

靠,真拗口,看图!
在这里插入图片描述
举例:要从链表1 2 3 4 中,在 2 后插入 5 。

#include <stdio.h>struct Test
{int data;struct Test *next;
};void addBehind(struct Test *head,int data,struct Test *new)
{struct Test *p = head;while(p != NULL){if(data == p->data){new->next = p->next;//先连新节点的后面p->next = new;      //再连新节点的前面return;}p = p->next;}
}void printLink(struct Test *head)
{int i;struct Test *p = head;while(p != NULL){printf("%d ",p->data);p = p->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;//t1的指针指向了t2的地址t2.next = &t3;t3.next = &t4;struct Test new ={5,NULL};addBehind(&t1,2,&new);printLink(&t1);return 0;
}

结果:

1 2 5 3 4
  • 1

思考一下,为什么上面要传入结构体new的地址?

像下图一样修改,传入的是结构体变量new,然后p->next再指向new的地址不就行啦?还不是一样把地址串了起来。

void addBehind(struct Test *head,int data,struct Test new)
{struct Test *p = head;while(p != NULL){if(data == p->data){new.next = p->next;p->next = &new;//形参函数结束就释放了 p->next指向这个位置会发生断错误return;}p = p->next;}
}addBehind(&t1,2,new);

结果是:段错误

Segmentation fault
  • 1

为啥?

因为上述中new只是子函数的一个形式参数罢了,地址空间是临时分配,当函数调用结束空间回收,你让一个指针p->next指向这里,必然导致段错误!

在指定节点前方插入新节点

第一种情况:不是1之前插入,链表头未发生改变

在这里插入图片描述第二种情况:是在1之前插入,链表头发生改变
在这里插入图片描述

举个栗子:(1)要从链表1 2 3 4 中,在 3 前插入 5 。

#include <stdio.h>struct Test
{int data;struct Test *next;
};struct Test *addInfront(struct Test *head,int data,struct Test *new)
{struct Test *p = head;if(data == head->data){new->next = head;    //先连新节点的后面head = new;return head;}while(p->next != NULL){if(data == p->next->data){new->next = p->next;//先连新节点的后面p->next = new;      //再连新节点的前面return head;}p = p->next;//让链表遍历起来}
}void printLink(struct Test *head)
{int i;struct Test *p = head;while(p != NULL){printf("%d ",p->data);p = p->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;//t1的指针指向了t2的地址t2.next = &t3;t3.next = &t4;struct Test new ={5,NULL};struct Test *head = &t1;head = addInfront(head,3,&new);printLink(head);return 0;
}

结果:

1 2 5 3 4
  • 1

(2)更改程序,在1之前插入5,结果:

5 1 2 3 4
  • 1

删除指定节点

在这里插入图片描述
删除的是头节点时,还要注意新头的替换

举例:删除 1 2 3 4中的 1

#include <stdio.h>struct Test
{int data;struct Test *next;
};struct Test *deNode(struct Test *head,int data)
{struct Test *p = head;if(data == head->data){head = head->next;return head;}while(p->next != NULL){if(data == p->next->data){p->next = p->next->next;return head;}p = p->next;}
}void printLink(struct Test *head)
{int i;struct Test *p = head;while(p != NULL){printf("%d ",p->data);p = p->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;//t1的指针指向了t2的地址t2.next = &t3;t3.next = &t4;struct Test *head = &t1;head = deNode(head,1);printLink(head);return 0;
}

结果:

2 3 4
  • 1

删除 1 2 3 4中的4,结果:

1 2 3
  • 1

四、链表的动态创建

头插法创建链表

头一直是在变化的
在这里插入图片描述关键步骤:

new->next = head;//new直接指向原来的链表头
head = new;//赋予新的链表头

实际例子:

运用头插法创建链表,直接输入数据自动串成链表,想要结束时,输入数据999.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct test
{int data;struct test *next;
}test,*ptest;void printLink(ptest head)
{int i;ptest p = head;while(p != NULL){printf("%d ",p->data);p = p->next;}putchar('\n');
}ptest insertHead(ptest head,ptest new)
{if(head == NULL){head = new;}else{new->next = head;//先连新节点的后面   new往前拱head = new;      //再连新节点的前面   new变成新头(头插)}return head;}ptest creatLink(ptest head)
{ptest new;while(1){new = (ptest)malloc(sizeof(test));printf("请输入新的节点,输入999结束输入\n");scanf("%d",&new->data);if(new->data == 999){free(new);new = NULL;return head;}head = insertHead(head,new);}
}int main()
{ptest head = NULL;head = creatLink(head);printLink(head);return 0;
}

结果:

请输入新的节点,输入999结束输入
3
请输入新的节点,输入999结束输入
4
请输入新的节点,输入999结束输入
5
请输入新的节点,输入999结束输入
6
请输入新的节点,输入999结束输入
999
6 5 4 3 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

尾插法创建链表

在这里插入图片描述

关键步骤:

(1)遍历找到链表的尾部

while(p->next != NULL){p = p->next;
}
  • 1
  • 2
  • 3

(2)在尾部添加new

p->next = new;
  • 1

实际例子:

运用尾插法创建链表,直接输入数据自动串成链表,想要结束时,输入数据999.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct test
{int data;struct test *next;
}test,*ptest;void printLink(ptest head)
{int i;ptest p = head;while(p != NULL){printf("%d ",p->data);p = p->next;}putchar('\n');
}ptest insertTail(ptest head,ptest new)
{ptest p = head;if(p == NULL){head = new;return head;//没有此句段错误}while(p->next != NULL){p = p->next;//遍历找到尾巴}p->next = new;//new跟在屁股后面(尾插)return head;
}ptest creatLink(ptest head)
{ptest new;while(1){new = (ptest)malloc(sizeof(test));printf("请输入新的节点,输入999结束输入\n");scanf("%d",&new->data);if(new->data == 999){free(new);new = NULL;return head;}head = insertTail(head,new);}
}int main()
{ptest head = NULL;head = creatLink(head);printLink(head);return 0;
}

结果:

请输入新的节点,输入999结束输入
3
请输入新的节点,输入999结束输入
4
请输入新的节点,输入999结束输入
5
请输入新的节点,输入999结束输入
999
3 4 5 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

思考:当上面的inserTail函数更改为如下,会发生什么?

ptest insertTail(ptest head,ptest new)
{ptest p = head;if(head == NULL){head = new;}else{p->next = new;}return head;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

结果:可以发现无论怎样输入链表都只有第一个和最后一个数据

请输入新的节点,输入999结束输入
1
请输入新的节点,输入999结束输入
3
请输入新的节点,输入999结束输入
5
请输入新的节点,输入999结束输入
6
请输入新的节点,输入999结束输入
8
请输入新的节点,输入999结束输入
999
1 8 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

那是因为:使用尾插法,链表头一直未改变。然而在每一次的循环中,p->next都指向new,即为每次头都指向new。到最后链表中自然只有头和最新的new啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/266777.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

boolean类型默认值_「软帝学院」Java的基本数据类型

Java的基本数据类型Java的两大数据类型: 内置数据类型 引用数据类型内置数据类型Java语言提供了八种基本类型。六种数字类型(四个整数型&#xff0c;两个浮点型)&#xff0c;一种字符类型&#xff0c;还有一种布尔型。byte&#xff1a; byte数据类型是8位、有符号的&#xff0c…

五大板块(5)——字符串

参考&#xff1a;五大板块&#xff08;5&#xff09;——字符串 作者&#xff1a;丶PURSUING 发布时间&#xff1a; 2021-03-18 16:03:48 网址&#xff1a;https://blog.csdn.net/weixin_44742824/article/details/114982019 目录一、字符串的定义方式与输出二、字符串的结尾是…

哈尔滨阳光计算机学院是不是黄了,黑龙江这4所野鸡大学,常被误认为是名校,实则害人不浅...

在高考中拿到高分进入心仪的大学&#xff0c;几乎是所有高三党奋斗努力的目标。但并不是所有的考生都能得偿所愿&#xff0c;没有取得高分&#xff0c;想进入好大学&#xff0c;但是又不想复读再经历一次高三的磨砺。如果此时你收到了录取通知书或者电话&#xff0c;告知你被一…

android 打开支付宝扫码页_Chrome 85正式版发布:新增标签页分组功,网页多了也不乱...

IT服务圈儿有温度、有态度的IT自媒体平台文章转载自 OSCHINA 社区[http://www.oschina.net]原文标题&#xff1a;Chrome 85 稳定版发布&#xff0c;页面加载速度提升 10%谷歌今日发布了最新稳定版 Chrome 85。此版本将页面加载速度提高了 10%&#xff0c;并带来了许多标签页方面…

Windows使用技巧

摘自&#xff1a;这些技巧让你windows用起来很爽 —— 小工具&#xff0c;小技巧&#xff0c;删小广告&#xff0c;重装卸载残留 作者&#xff1a;丶PURSUING 发布时间&#xff1a; 2021-03-12 16:09:17 网址&#xff1a;https://blog.csdn.net/weixin_44742824/article/detail…

iOS开发缓存机制之—内存缓存机制

在IOS应用程序开发中&#xff0c;为了减少与服务端的交互次数&#xff0c;加快用户的响应速度&#xff0c;一般都会在iOS设备中加一个缓存的机制。这篇文章将介绍一下如何在iOS设备中进行缓存&#xff0c;本文先介绍一下将内容缓存到内存中&#xff0c;下一篇文章就介绍一下在i…

云计算机教室怎么布线,云和县实验小学计算机教室综合布线及计算机安装预算方案.doc...

云和县实验小学计算机教室综合布线及计算机安装预算方案.doc (2页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;17.90 积分&#xfeff;云和县教育装备和勤工俭学办公室计算机教室改造工程参数设备名…

循环造数据_项目管理数据与信息--DIKW模型

开头的话在PMP中&#xff0c;有一块内容是“项目管理数据与信息&#xff1a;工作绩效数据&#xff08;Work Performance Data&#xff09;&#xff0c;工作绩效信息&#xff08;Work Performance Information&#xff09;&#xff0c;工作绩效报告&#xff08;Work Performance…

基于C语言Ncurse库和链表的简单贪吃蛇小游戏

参考&#xff1a;基于C语言Ncurse库和链表的简单贪吃蛇小游戏 作者&#xff1a;三速何时sub20 发布时间&#xff1a;2020-09-29 10:23:51 网址&#xff1a;https://blog.csdn.net/weixin_44234294/article/details/108829135?spm1001.2014.3001.5501 Ncurses库相关介绍 ncurse…

C 内存分配【转】

c 内存分配 1、程序代码区:存放函数体的二进制代码。 2、全局区数据区&#xff1a;全局数据区划分为三个区域。 全局变量和静态变量的存储是放在一块的。初始化的全局变量和静态变量在一块区域&#xff0c;未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。常量数…

STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结

摘自&#xff1a;STM32F103五分钟入门系列&#xff08;一&#xff09;跑马灯&#xff08;库函数寄存器&#xff09;加编程模板GPIO总结 作者&#xff1a;自信且爱笑‘ 发布时间&#xff1a; 2021-04-28 21:17:40 网址&#xff1a;https://blog.csdn.net/Curnane0_0/article/det…

计算机没有程序,计算机小知识:想尝试写程序却没有电脑?这个在线编辑器满足你...

大家好&#xff0c;我是零一&#xff0c;昨天的文章《计算机小知识&#xff1a;手把手教你写出自己的第一个程序&#xff1a;Hello World》发表后&#xff0c;没几分钟就有小伙伴问我&#xff0c;没有电脑&#xff0c;但是真的很想尝试去学习一下编程&#xff0c;应该怎么办&am…

微信小程序时间戳的转换及调用

13位 的时间戳&#xff0c;如下图&#xff1a; 效果图: 1.(utils.js里面的代码): function formatTime(timestamp, format) {const formateArr [Y, M, D, h, m, s];let returnArr [];let date new Date(timestamp); //13位的时间戳, 如果不是13位的, 就要乘1000,就像这样…

基于Wemos D1的感应开盖垃圾桶

参考&#xff1a;基于Wemos D1的感应开盖垃圾桶&#xff08;增加自己的代码实现部分&#xff09; 作者&#xff1a;LEO-max 发布时间&#xff1a;2020-12-29 15:21:26 网址&#xff1a;https://blog.csdn.net/zouchengzhi1021/article/details/111880104?spm1001.2014.3001.55…

电脑计算机主板不启动,电脑主板不能启动的解决方法

电脑主板不能启动的解决方法主板又称主机板、系统板、逻辑板、母板、底板等&#xff0c;是构成复杂电子系统例如电子计算机的中心或者主电路板。下面给大家介绍电脑主板不能启动的解决方法&#xff0c;欢迎阅读!电脑主板不能启动的解决方法电脑主板不能启动的解决方法一&#x…

WEB前端 CSS(非布局)

目录 WEB前端 CSSCSS引入方式CSS结构CSS选择器直接选择器组合选择器分组选择器 也叫并集选择器属性选择器伪类选择器伪元素选择器CSS选择器是一个查找的过程&#xff0c;高效的查找影响页面加载的效率CSS选择器的优先级CSS声明CSS非布局声明CSS布局声明除了css 对样式有影响&am…

二叉树的三叉链表存储和基本操作

三叉链表存储表示 改进于二叉链表&#xff0c;增加指向父节点的指针&#xff0c;能更好地实现结点间的访问。 存储结构 /* 二叉树的三叉链表存储表示 */typedef struct BiTPNode{TElemType data;struct BiTPNode *parent,*lchild,*rchild; /* 双亲、左右孩子指针 */}BiTPNode,*…

麟龙指标通达信指标公式源码_通达信指标公式源码单阳不破主图指标公式

做价值的传播者&#xff0c;一路同行&#xff0c;一起成长问题&#xff1a;怎样才能每天都收到这类文章&#xff01;答案&#xff1a;只需点击上方《通达信公式指标》{通达信单阳不破}MA30: MA(C,30 ),COLORGREEN;MA30_: IF(MA30>REF(MA30,1),MA30,DRAWNULL),COLORMAGENTA;阳…

高考英语口语测试软件,练习英语口语的app有哪些

随着国际化的发展&#xff0c;英语越来越普遍。英语中口语也是很重要的成分之一。也是跟老外交流或者英语考试的重要考点之一。我们有很多方法锻炼口语。什么方法最快捷最有效方便&#xff1f;下面我们看看几款最受欢迎的英语口语练习app。练习口语的app1、口语侠一款非常实用的…

chkconfig命令会立即生效吗_UG绘制波纹管,整体变形命令你会用吗?

最近又有小伙伴问我波纹管怎么画了&#xff0c;这个以前教过大家&#xff0c;文章名字叫饮料吸管和排水管&#xff0c;看来这个名字不够专业&#xff0c;大家找不到啊&#xff0c;今天就来重新绘制一个&#xff0c;用一个新的方法&#xff0c;大家来额外学习一下&#xff0c;了…