【数据结构】单链表

 🔥博客主页:小王又困了

📚系列专栏:数据结构

🌟人之为学,不日近则日退 

❤️感谢大家点赞👍收藏⭐评论✍️


目录

一、什么是链表 

1.1链表的概念及结构

1.2单链表的结构

二、链表的实现

📒2.1创建节点

📒2.2头插

📒2.3头删

📒2.4尾插 

💭链表为空的插入

💭链表不为空  

📒2.5尾删

📒2.6查找

📒2.7在pos位置之前插入

📒2.8在pos位置之后插入

📒2.9删除pos位置


🗒️前言

在上一期中我们学习了顺序表,但它却有缺点,例如头插或从中间插入效率低等,而链表可以有效的解决这些问题。那么就让我们走进链表的学习。

一、什么是链表 

1.1链表的概念及结构

概念::链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

结构

 注意:

1.链式结构在逻辑上是连续的,但在物理上不一定连续。

2.节点都是从堆上申请的。

3.从堆上申请空间,是按一定策略分配的,申请的空间可能连续,也可能不连续。

1.2单链表的结构

typedef int STLDataType;typedef struct STLNode
{STLDataType date;struct STLNode* next;   
}STLNode;

这种链表被称为无头+单向+非循环链表

二、链表的实现

📒2.1创建节点

我们想使用链表来实现各种功能得先有链表,所以首先使用malloc创建节点。

STLNode* BuyListNode(STLDataType x)
{STLNode* newnode = (STLNode*)malloc(sizeof(STLNode));if (newnode == NULL){perroe("malloc");exit(-1);}newnode->date = x;newnode->next = NULL;return newnode;
}

 

📒2.2头插

要想让链表连起来,就要让newnode->next存放下一个节点的地址,也就是旧链表phead的值,然后将newnode的地址存放在phead中,形成新的链表。无论一开始有没有节点,头插都是相同的。

//头插
void STLPushFront(STLNode** pphead, STLDataType x)
{STLNode* newnode = BuyListNode(x);newnode->next = *pphead;*pphead = newnode;
}

📒2.3头删

 头删时如果先释放空间,就会找不到下一个节点的地址;如果先把下一个节点的地址赋给*pphead就会导致无法释放空间,所以我们要创建一个临时变量来存放下一个节点的地址。

//头删
void STLPopFront(STLNode** pphead)
{assert(*pphead);STLNode* newnode = (*pphead)->next;free(*pphead);*pphead = newnode;
}

📒2.4尾插 

我们在尾插时,会有两种情况,链表为空的插入有其他节点的尾插。第一种情况会出现一些理解性的错误,接下来就让我们学习学习这两种尾插的情况。

💭链表为空的插入

当我们传递的是plist的值,屏幕上并没有打印出我们想要的结果。这是为什么呢?

形参是实参的一份临时拷贝,形参的改变不会影响实参,phead的改变不会影响plist。 临时变量出作用域销毁,phead和newnode销毁,找不带开辟的节点,会造成内存泄漏。

正确做法是要将plist的地址传递过去,我们通过解引用就可以改变plist。plist中存放的是指针,我们传递指针的地址要用二级指针接收。

 

💭链表不为空  

链表不为空时,我们要找到尾节点。这里我们要注意不能使用 tail!=NULL 判断。这样我们无法把链表连接起来。

//尾插
void STLPushBack(STLNode** pphead, STLDataType x)
{assert(pphead);STLNode* newnode = BuyListNode(x);if (NULL == *pphead){*pphead = newnode;}else{STLNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

📒2.5尾删

在尾删时也有两种情况,一种是有很多节点,另一种是只剩一个节点,当删最后一个节点时,要改变plist的值,所以我们要传递plist的指针。我们要使用两个指针,当后面的指针释放后,可以利用前面的指针将最后一个节点的next置为空。

//尾删
void STLPopBack(STLNode** pphead)
{assert(*pphead);//只剩一个if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//多个else{STLNode* prev = NULL;STLNode* tail = *pphead;while (tail->next){prev = tail;tail = tail->next;}free(tail);prev->next = NULL;}
}

📒2.6查找

循环判断时不要使用cur->next,这样写最后一个数据要单独处理不方便,找到时就返回此时的地址。

//查找
STLNode* STLFind(STLNode* phead, STLDataType x)
{STLNode* cur = phead;while (cur != NULL){if (cur->date == x){return cur;}cur = cur->next;}return 0;
}

📒2.7在pos位置之前插入

在pos位置之前插入有一种特殊的情况就是头插,要改变plist的值,我们要传二级指针进去。同时我们要创建一个指针变量,找到pos之前的位置,才能使链表连接起来。

void STLInsert(STLNode** pphead, STLNode* pos, STLDateType x)
{assert(pos);if(pos == *pphead){STLPushFront(pphead, x);}else{STLNode* prev = *pphead;while(prev->next != pos){prev = prev->next;}STLNode* newnode = BuySListNode(x);newnode->next = pos;prev->next = newnode;}}

📒2.8在pos位置之后插入

这里我们要注意地址赋值的顺序,顺序不对会造成内存泄漏。如果先把newnode的地址赋给pos的指针域,就会丢失下一个节点的地址。

void STLInsertAfter(STLNode* pos, STLDateType x)
{    assert(pos);STLNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;}

📒2.9删除pos位置

有可能删除的是头节点,所以要传递二级指针。

void STLErase(STLNode** pphead, STLNode* pos)
{assert(pos);if(pos == *pphead){STLPopFront(pphead, x);}else{STLNode* prev = *pphead;while(prev->next != pos){prev = prev->next;}prev->next = newnode;free(pos);}}

本次的内容到这里就结束啦。希望大家阅读完可以有所收获,同时也感谢各位读者三连支持。文章有问题可以在评论区留言,博主一定认真认真修改,以后写出更好的文章。你们的支持就是博主最大的动力。

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

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

相关文章

Elasticsearch官方测试数据导入

一、数据准备 百度网盘链接 链接:https://pan.baidu.com/s/1rPZBvH-J0367yQDg9qHiwQ?pwd7n5n 提取码:7n5n文档格式 {"index":{"_id":"1"}} {"account_number":1,"balance":39225,"firstnam…

C++的auto究竟是何方神圣

C的auto究竟是何方神圣 前言🙌auto(C 11) 的使用细则auto是什么? auto声明的变量是在什么时期被编译器推导出来呢?为什么使用auto进行定义变量时,必须进行初始化? auto 的使用场景auto与指针和引…

【Linux】【预】配置虚拟机的桥接网卡+nfs

【Linux】【预】配置虚拟机的桥接网卡 1. 配置VM虚拟机的桥接网络2 配置Win10中的设置3.配置Linux中的IP4. 串口连接开发板,配置nfs5 修改网络文件6 验证nfs 是否成功总结 1. 配置VM虚拟机的桥接网络 右击设置,选择添加网络,按照如下顺序操作…

笔记本WIFI连接无网络【实测有效,不用重启电脑】

笔记本Wifi连接无网络实测有效解决方案 问题描述: 笔记本买来一段时间后,WIFI网络连接开机一段时间还正常连接,但是过一段时间显示网络连接不上,重启电脑太麻烦,选择编写重启网络脚本解决。三步解决问题。 解决方案&a…

Cadvisor+InfluxDB+Grafan+Prometheus(详解)

目录 一、CadvisorInfluxDBGrafan案例概述 (一)Cadvisor Cadvisor 产品特点: (二)InfluxDB InfluxDB应用场景: InfluxDB主要功能: InfluxDB主要特点: (三&#…

MySQL— 基础语法大全及操作演示!!

MySQL—— 基础 一、MySQL概述1.1 、数据库相关概念1.2 、MySQL 客户端连接1.3 、数据模型 二、SQL2.1、SQL通用语法2.2、SQL分类2.3、DDL2.4、DML2.5、DQL2.6、DCL 三、函数四、约束五、多表查询六、事务 一、MySQL概述 1.1 、数据库相关概念 数据库、数据库管理系统、SQL&a…

测试狗丨电镜技术在微观结构表征中的解决方案交流会圆满结束

8月3日,由成都测试狗携手赛默飞世尔科技、四川省增材制造技术协会联合举办的线下交流会——《电镜技术在微观结构表征中的解决方案》在测试狗总部成功举行。本次会议旨在促进电子显微镜技术在材料科学、生命科学、环境科学等领域的交流、发展和应用,共同…

【Docker】AUFS、BTRFS、ZFS、储存池详解

洁洁的个人主页 我就问你有没有发挥! 知行合一,志存高远。 前言 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是…

实战指南:使用OpenCV 4.0+Python进行机器学习与计算机视觉

💂 个人网站:【办公神器】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 目录 1.背景2. 安装和配…

微服务与Nacos概述-2

微服务间消息传递 微服务是一种软件开发架构,它将一个大型应用程序拆分为一系列小型、独立的服务。每个服务都可以独立开发、部署和扩展,并通过轻量级的通信机制进行交互。 应用开发 common模块中包含服务提供者和服务消费者共享的内容 provider模块是…

SQL-每日一题【1193. 每月交易 I】

题目 Table: Transactions 编写一个 sql 查询来查找每个月和每个国家/地区的事务数及其总金额、已批准的事务数及其总金额。 以 任意顺序 返回结果表。 查询结果格式如下所示。 示例 1: 解题思路 1.题目要求我们查找每个月和每个国家/地区的事务数及其总金额、已批准的事务数…

Python之特殊属性、对象的浅拷贝和深拷贝

一、特殊属性 Python对象中包含了很多双下划线开始和结束的属性,这些是特殊属性,有特殊用法。这里我们列出常见的特殊属性: 特殊属性含义obj.__dict__对象的属性字典obj.__class__对象所属的类class.__bases__表示类的父类(多继承时&#x…