《数据结构学习笔记---第三篇》---单链表具体实现

目录

1.链表

1.1 链表的概念及结构

2.不带头单链表的实现

 2.1创建头文件“SList.h”

2.2 创建具体接口实现文件SList.c

2.2.1打印

2.2.2申请链表结点

2.2.3创建一个长度为n的链表

 2.2.4尾插尾删

2.2.5头插头删

2.2.6寻找x元素,返回pos

2.2.7插入和删除pos之后的位置

 2.2.8插入pos之前的位置和删除pos位置

2.2.9 销毁链表

3.主函数的实现



1.链表

1.1 链表的概念及结构

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

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

1. 单向、双向

2. 带头、不带头

3. 循环、非循环

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结 构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向 循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而 简单了,后面我们代码实现了就知道了。

2.不带头单链表的实现

 2.1创建头文件“SList.h”

  ​​​​​为什么要创立头文件

#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;SLTNode* BuySLTNode(SLTDataType);//申请结点SLTNode* CreateSList(int n);//创建一个多长的链表void SLTPrint(SLTNode* phead);void SLTPushBack(SLTNode**pphead,SLTDataType x);
void SLTPopBack(SLTNode**pphead);
void SLTPushFront(SLTNode** pphead, SLTDataType x);
void SLTPopFront(SLTNode** pphead);SLTNode* SListFind(SLTNode* plist, SLTDataType x);//找x的位置void SListInsertAfter(SLTNode* pos, SLTDataType x);//插入pos之后的位置
void SListErasetAfter(SLTNode* pos);//删除pos后面的位置void SListInsert(SLTNode**pphead,SLTNode* pos, SLTDataType); //插入pos之前的位置 
void SLTErase(SLTNode** pphead,SLTNode* pos);//删除posvoid SLTDestroy(SLTNode** pphead);//销毁链表

这里我们用来结构体的嵌套来定义单链表的节点结构体的嵌套定义

2.2 创建具体接口实现文件SList.c

先引用#include "SList.h"

2.2.1打印

void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;/*if (cur == NULL){printf("NULL");}*/while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

 在这里我们没有断言assert,如果头指针为空指针,程序就会打印出NULL。

2.2.2申请链表结点

SLTNode* BuySLTNode(SLTDataType x)//申请结点
{SLTNode* newnode= (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("melloc fail");exit(-1);}newnode->data = x;newnode->next = NULL;return newnode;
}

 在这里我们用了扩容,但我们使用的是malloc,和顺序表有所不同的是我们并不需要异地扩容,对于链表来说存储的位置本就是随机的,不需要整块连续的空间。

2.2.3创建一个长度为n的链表

SLTNode* CreateSList(int n)//创建一个多长的链表
{SLTNode* phead = NULL, * ptail = NULL;int x = 0;for (int i = 0 ; i < n; i++){SLTNode* newnode = BuySLTNode(i);if (phead == NULL){phead = ptail = newnode;}else{ptail->next = newnode;ptail = newnode;}}return phead;
}

 2.2.4尾插尾删

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* cur =*pphead;SLTNode* newnode = BuySLTNode(x);if (*pphead == NULL){*pphead =newnode;}else {while (cur->next){cur = cur->next;}cur->next = newnode;}
}void SLTPopBack(SLTNode** pphead)
{assert(*pphead);SLTNode* tail = *pphead;SLTNode* prev = *pphead;if ((* pphead)->next == NULL){free(*pphead);*pphead = NULL;}else {while (tail->next->next){tail = tail->next;}free(tail->next);tail->next = NULL;}
}

 注意:

  • 我们可以看到我们这里与顺序表明显不同的是我们这里传入了二级指针,这到底是为什么,看这篇博文单链表尾插过程中为什么传入二级指针
  • 尾删时注意 free(tail)与 free(tail->next)的区别,其实原理和上述问题类似,因为后者修改的是结构体指针直接改变到了结构体,而仅仅free(tail)会导致出了函数的作用域,tail栈帧销毁,无法真正的改变到结构体

2.2.5头插头删

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;}void SLTPopFront(SLTNode** pphead) {assert(*pphead);SLTNode* cur = *pphead;cur = cur->next;free(*pphead);*pphead = cur;}

2.2.6寻找x元素,返回pos

SLTNode* SListFind(SLTNode* plist, SLTDataType x)
{assert(plist);SLTNode* cur = plist;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;}//找x的位置

2.2.7插入和删除pos之后的位置

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{/*if (pos == NULL){SLTPushBack(pos, x);}else {*/assert(pos);SLTNode*newnode=BuySLTNode(x);SLTNode* cur = pos;SLTNode* lnext = pos->next;cur->next = newnode;newnode->next = lnext;/*}*/
}//插入pos之后的位置}

 2.2.8插入pos之前的位置和删除pos位置

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x) {assert(pos);if (*pphead == pos){SLTPushFront(pphead, x);}else{SLTNode* prev = *pphead;SLTNode* newnode = BuySLTNode(x);/*while (prev->next){if (prev->next == pos){prev->next = newnode;newnode->next = pos;}prev = prev->next;}*/while (prev->next->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}} //插入pos之前的位置void SLTErase(SLTNode** pphead, SLTNode* pos)//删除pos
{assert(pos);//写错了if (pos== *pphead){SLTPopFront(pphead);}else {SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* lnext = pos;prev->next = prev->next->next;free(pos);}
}//删除pos

2.2.9 销毁链表

void SLTDestroy(SLTNode** pphead)
{SLTNode* cur = *pphead;while (cur){SLTNode* tail = cur->next;free(cur);cur = tail;cur = cur->next;}*pphead = NULL;
}//销毁链表

注意置空,防止野指针,打印的时候没断言。

3.主函数的实现

#include "SList.h"
void SListTest1() {SLTNode* n1 = BuySLTNode(1);SLTNode* n2 = BuySLTNode(2);SLTNode* n3 = BuySLTNode(3);SLTNode* n4 = BuySLTNode(4);SLTNode* n5 = BuySLTNode(5);n1->next = n2;n2->next = n3;n3->next = n4;n4->next = n5;n5->next = NULL;
//	SLTNode*plist=CreateSList(5);SLTPrint(n1);
}
void SListTest2() {SLTNode* plist = CreateSList(1);SLTPrint(plist);/*SLTPushBack(&plist, 100);*/SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPushFront(&plist,9);SLTPushFront(&plist,99);SLTPushFront(&plist,999);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);
}
void SListTest3() {SLTNode* plist = CreateSList(5);SLTPrint(plist);/*SLTNode*p=SListFind(plist, 3);SListInsertAfter(p, 100);SLTPrint(plist);SListErasetAfter(p);SLTPrint(plist);*/SLTNode*p = SListFind(plist, 0);/*SListInsert(&plist, p, 999);SLTPrint(plist);*/SLTErase(&plist, p);SLTPrint(plist);SLTDestroy(&plist);SLTPrint(plist);
}int main()
{SListTest1();SListTest2();SListTest3();return 0;
}

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

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

相关文章

量子专家联合开展欧洲之星项目“SupremeQ”以实现光量子计算优势

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨王珩 编译/排版丨浪味仙 沛贤 深度好文&#xff1a;1800字丨10分钟阅读 近日&#xff0c;英国全栈光量子计算系统公司 ORCA Computers、德国单光子探测器提供商 Pixel Photonics、丹麦量…

餐饮服务升级:微信小程序扫码点餐制作

餐饮体验的升级不仅体现在食物的质量和环境的营造上&#xff0c;更在于服务的便捷性和智能化。扫码点餐小程序正是这一理念的体现&#xff0c;它通过简化点餐流程&#xff0c;为顾客和商家带来了双赢的局面。那么商家微信小程序扫码点餐制作的流程是怎么样呢&#xff1f;怎么快…

二叉树的遍历及线索二叉树试题解析

一、单项选择题 01.在下列关于二叉树遍历的说法中&#xff0c;正确的是( C ). A.若有一个结点是二叉树中某个子树的中序遍历结果序列的最后一个结点&#xff0c;则它一定是该子树的前序遍历结果序列的最后一个结点 B.若有一个结点是二叉树中某个子树的前序遍历结果序列的最后一…

安卓国内ip代理app,畅游网络

随着移动互联网的普及和快速发展&#xff0c;安卓手机已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;由于地理位置、网络限制或其他因素&#xff0c;我们有时需要改变或隐藏自己的IP地址。这时&#xff0c;安卓国内IP代理App便成为了一个重要的工具。虎观代理…

Chrome之解决:浏览器插件不能使用问题(十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

c语言知识点整理------基础c语言框架,数据类型,变量常量,注释

前言 本文不涉及讲解原理&#xff0c;用简洁明了的风格&#xff0c;去整理方便查阅的知识点。 &#xff08;适合有编程基础&#xff0c;或者需要作为笔记的人群使用&#xff09; 程序基本框架 结果会输出hello world。 程序的执行 c语言属于编译型语言。 代码执行分为五个…

文件上传漏洞-服务端检测

服务端检测 服务端检测就是网站对用户上传的文件的检测代码放置在服务器里&#xff0c;当用户上传的文件通过了检测才会被允许保存在服务器里。 MIME类型检测 MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。用来表示文档、文件或字节流的…

第115讲:Mycat核心配置文件各项参数的作用以及概念

文章目录 1.Mycat配置文件相关概念2.Schema配置文件3.Rule配置文件4.Server配置文件 1.Mycat配置文件相关概念 在Mycat中核心的配置文件有schema.xml和rule.xml以及server.xml三个&#xff0c;其中schema.xml是用来配置数据库、表、读写分离、分片节点、分片规则等信息&#x…

精准营销的秘密:独立站如何通过大数据与AI技术实现个性化定制

在当今电商市场竞争激烈的背景下&#xff0c;电商行业逐渐步入个性化、精细化的运营时代。独立站作为电商领域的重要组成部分&#xff0c;其推广策略也在不断地进行创新与升级。个性化定制策略以其精准、高效的特点&#xff0c;正逐渐成为独立站推广的新宠。本文Nox聚星将和大家…

PostgreSQL关系型数据库介绍与部署

使用背景 在过去的几年中&#xff0c;PostgreSQL的使用量逐渐增加&#xff0c;而Oracle和MySQL的使用量则有所下降。这主要是由于以下几个原因&#xff1a;开源和免费、功能丰富、可扩展性强、安全性高、跨平台支持好、社区活跃、成熟稳定。这些因素使得PostgreSQL成为了许多开…

针对COT控制模式下低ESR电容造成次谐波振荡问题的片内斜波补偿方案

COT模式&#xff1a;MOS管固定导通时间控制模式&#xff0c;关断时间由输出反馈电压与内部基准源的相较值决定。 RBCOT控制模式&#xff1a;Ripple-Based COT基于纹波的固定导通时间控制方法&#xff0c;特别的是环路控制部分主要有固定导通时间发生装置及比较器组成。RBCOT控…

Java:反射 reflection ( 概念+相关类+使用方法)

文章目录 一、反射(reflection)1.概念优点&#xff1a;缺点 2.反射的相关类1.Class类1.**反射机制的起源**2.获得类相关的方法3.获得类中属性的相关方法4.获得类中注解相关的方法5.获得类中构造器相关的方法6.获得类中方法相关的方法 2.获取Class对象的三种方法&#xff1a;1.使…

剑指Offer题目笔记19(二分查找)

面试题68&#xff1a; 问题&#xff1a; ​ 输入一个排序的整形数组nums和一个目标值t&#xff0c;如果数组nums中包含t&#xff0c;则返回在数组中的下标&#xff0c;否则返回按照顺序插入到数组的下标。 解决方案&#xff1a; ​ 使用二分查找。每次二分查找都选取位于数组…

Days 35 ElfBoard板对Java的支持

Java作为一种功能强大且广泛应用的编程语言&#xff0c;具有广泛的适应性和实用性。在ELF 1开发板上集成Java支持&#xff0c;无疑将赋予嵌入式开发者更广阔的选择空间&#xff0c;今天就为各位小伙伴详细解析如何在ELF 1开发板上成功部署和运行Java环境。 1.拷贝两个压缩包到E…

国内IP代理手机软件推荐:功能、选择与使用指南

在移动互联网日益普及的今天&#xff0c;手机已经成为我们生活中不可或缺的一部分。而在使用手机上网的过程中&#xff0c;有时我们可能需要改变或隐藏自己的IP地址&#xff0c;以满足特定的网络需求或提高安全性。这时&#xff0c;国内IP代理手机软件便成为了一个重要的工具。…

基于SpringBoot+Vue+Mybatis的408刷题小程序管理端

简介 原始数据&#xff1a;书目信息、章节信息、题目信息、系统菜单、系统角色、系统用户。 主要任务&#xff1a;系统主要采用spring boot作为后端框架&#xff0c;前端使用vueelementUI&#xff0c;为408刷题小程序提供一个方面的管理和维护的任务&#xff0c;主要功能包括…

IS-IS路由

概览&#xff1a; Intermediate System-to-Intermediate System&#xff0c;中间系统到中间系统协议 IS-IS--IGP--链路状态协议--AD值&#xff1a;115 IS--中间系统&#xff08;路由器&#xff09; ES--终端系统&#xff08;PC&#xff09; 在早期IS-IS的开发并不是为了IP…

Python学习之-正则表达式

目录 前言&#xff1a;1.re.serach1.1例子&#xff1a; 2.re.match2.1示例1&#xff1a;2.2 示例2&#xff1a; 3.re.findall3.1 示例 4.re.fullmatch4.1 示例1&#xff1a;4.2 示例2: 5.re.split5.1 示例1:5.2 示例2&#xff1a;5.3 示例3&#xff1a; 6.re.sub6.1 示例&#…

vue3+Vite+TS项目,配置ESlint和Prettier

创建vue3项目 实操过的有两种方式 1.vue脚手架2.vite&#xff08;推荐&#xff0c;也是尤大大团队研发&#xff09; 具体怎么新建一个vue3项目就不多讲了&#xff0c;可以按照官方文档来 创建后的文件目录长这样 多提一句&#xff0c;vite也会随着时间不断迭代&#xff0c;后…

【绘图案例-自定义进度条 Objective-C语言】

一、好,我们接着来说这个自定义进度条 1.这个Slider啊,简单的这个value属性,介绍完了,以后,监听也可以监听的到了,接下来,我们来做这个自定义进度条啊, 那么,首先啊,我是这么想的,在这个slider的最小值、和、最大值、我给它改成0、到、1、 因为如果这样的话,到时候…