当前位置: 首页 > news >正文

数据结构第三讲:单链表的实现

数据结构第三讲:单链表的实现

  • 1.什么是单链表
  • 2. 节点
  • 3.单链表的实现
    • 3.1节点的结构
    • 3.2打印单链表
    • 3.3申请一个新节点
    • 3.4单链表尾部插入
    • 3.5单链表头部插入
    • 3.6单链表的尾部删除
    • 3.7单链表头部删除
    • 3.8查找
    • 3.9在指定位置之前插入数据
    • 3.10在指定位置之后插入数据
    • 3.11删除pos节点
    • 3.12删除pos之后的节点
    • 3.13销毁链表

1.什么是单链表

单链表也是顺序表的一种,它在逻辑结构上是连续的,在物理结构上不一定是连续的

就像是火车一样,有一个火车头、很多节车厢,每相邻的车厢会通过钩子进行链接,单链表中,一节一节的车厢被成为是一个一个的节点,就像这样:
在这里插入图片描述

2. 节点

那么每一个节点到底是怎么样来链接的呢?其实每一个节点中只存储两个数据:需要存储的数据和指向下一个节点的指针,这样通过指针就能够找到下一个节点了

3.单链表的实现

3.1节点的结构

节点只需要存储两个内容,所以实现起来也会比较轻松:

typedef int SLTDateType;typedef struct SListNode
{//存储数据SLTDateType date;//存储框架struct SListNode* next;
}SLTNode;

3.2打印单链表

我们先使用节点结构体自行创建一些节点,然后自行将节点链接起来,如下:

	//通过动态内存分配创建节点SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));node1->date = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->date = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->date = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->date = 4;SLTNode* node5 = (SLTNode*)malloc(sizeof(SLTNode));node5->date = 5;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = node5;node5->next = NULL;

然后我们实现一下链表的打印功能:
打印我们使用一个while循环即可,因为链表最后一个节点指向的空间为NULL,所以我们可以以此为一个突破点,作为循环的终止条件,实现如下:

void SLTPrint(SLTNode* phead)
{//对于打印,使用一个循环即可SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->date);pcur = pcur->next;}printf("NULL\n");
}

3.3申请一个新节点

上述我们自行申请的一个新节点太过于费事费力了,我们应该试着写一个函数,让函数来帮我们申请空间,实现起来也不困难:

//申请一个新节点
SLTNode* SLBuyNode(SLTDateType x)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("malloc faile!");exit(1);}node->date = x;node->next = NULL;return node;
}

3.4单链表尾部插入

看图:
在这里插入图片描述
我们只需要找到链表的末端,将最后一个节点中的地址指向新的节点,然后将新的节点中的指针指向NULL即可:

//单链表尾部插入
//注意:这里要使用二级指针,因为如果链表中没有节点时,我们要改变头指针的值,让它指向第一个节点的地址
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{assert(pphead);//对于插入,首先都要先创建一个节点,才能够实现插入SLTNode* newnode = SLBuyNode(x);//插入方法//1.找到最后一个节点if (*pphead == NULL){*pphead = newnode;}else{SLTNode* pcur = *pphead;while (pcur->next){pcur = pcur->next;}pcur->next = newnode;}
}

3.5单链表头部插入

在这里插入图片描述
只需要将刚开辟节点中的指针指向原来的头节点地址,并改变头节点的指向即可:

//单链表头部插入
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = SLBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}

3.6单链表的尾部删除

在这里插入图片描述
只需要将最后一个节点的空间释放掉,然后将释放后的最后一个节点中的指针指向NULL即可,需要注意的是:这里需要找到释放位置前的节点,当只存在一个节点时,最后一个节点前的空间是不能够进行访问的,这里需要单独讨论:

//单链表尾部删除
void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);//将只有一个节点的情况单独讨论if ((*pphead)->next == NULL)//这里要注意:->的优先级要大于* 所以要将*pphead加上小括号{free(*pphead);*pphead = NULL;}else{//先找到最后一个数据的前一个数据SLTNode* pcur = *pphead;SLTNode* prev = NULL;while (pcur->next){prev = pcur;pcur = pcur->next;}prev->next = NULL;free(pcur);pcur = NULL;}
}

3.7单链表头部删除

在这里插入图片描述
头部删除相对简单,只需要释放空间,然后改变头指针的位置即可:

//单链表头部删除
void SLTPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* prev = (*pphead)->next;free(*pphead);*pphead = prev;
}

3.8查找

查找查找的是数据所在的位置,返回的是节点的地址:

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{assert(phead);SLTNode* pcur = phead;while (pcur){if (pcur->date == x){return pcur;}pcur = pcur->next;}return NULL;
}

3.9在指定位置之前插入数据

在这里插入图片描述
在指定位置之前插入数据,需要找到指定位置前的那个节点,这里还需要单独讨论,因为当只存在一个节点时,前面的空间是无法访问的,和上边一样,然后我们只需要改变节点中指针的指向即可

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDateType x)
{assert(pphead);assert(pos);//当在第一个节点前进行插入时if (*pphead == pos){SLTPushFront(pphead, x);}else{//先创建一个节点SLTNode* newnode = SLBuyNode(x);SLTNode* pcur = *pphead;while (pcur->next != pos){pcur = pcur->next;}pcur->next = newnode;newnode->next = pos;}
}

3.10在指定位置之后插入数据

在这里插入图片描述
在指定位置之后插入数据,因为已经知道了在哪个位置进行插入,所以我们就能够直接找到下一个节点的地址,直接改变地址指向即可:

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos);//先创建一个节点SLTNode* newnode = SLBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}

3.11删除pos节点

在这里插入图片描述
删除节点,只需要释放空间,改变指针指向即可:

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pos);assert(*pphead && pphead);if (*pphead == pos){SLTPopFront(pphead);}else{SLTNode* pcur = *pphead;while (pcur->next != pos){pcur = pcur->next;}pcur->next = pos->next;free(pos);pos = NULL;}
}

3.12删除pos之后的节点

在这里插入图片描述
释放空间,改变指向:

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos && pos->next);pos->next = pos->next->next;free(pos->next);pos->next = NULL;
}

3.13销毁链表

在这里插入图片描述

使用循环销毁即可:

//销毁链表
void SListDestory(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* prew = *pphead;while (prew){SLTNode* pcur = prew->next;free(prew);prew = pcur;}*pphead = NULL;
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • GitLab添加TortoiseGIT生成SSH Key
  • Java 中如何执行命令行方法
  • 初识godot游戏引擎并安装
  • JAVA基础知识4(static、继承)
  • Spring中存储Bean的相关注解及用法
  • 【C++】类和对象之继承
  • 数组算法--二分查找
  • php 做一个mqtt按钮,发布触发信号
  • Unity UGUI 之 Input Field
  • 深入浅出WebRTC—Pacer
  • elementPuls 表格反选实现
  • 【LLM】-07-提示工程-聊天机器人
  • HarmonyOS应用开发者高级认证,Next版本发布后最新题库 - 答案纯享版
  • Git添加和提交文件
  • [亲测可用]俄罗斯方块H5-网页小游戏源码-HTML源码
  • [deviceone开发]-do_Webview的基本示例
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • AzureCon上微软宣布了哪些容器相关的重磅消息
  • CSS实用技巧
  • input实现文字超出省略号功能
  • Magento 1.x 中文订单打印乱码
  • node学习系列之简单文件上传
  • Puppeteer:浏览器控制器
  • Shadow DOM 内部构造及如何构建独立组件
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • webgl (原生)基础入门指南【一】
  • Xmanager 远程桌面 CentOS 7
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 聊聊sentinel的DegradeSlot
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 找一份好的前端工作,起点很重要
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • # C++之functional库用法整理
  • ### RabbitMQ五种工作模式:
  • #微信小程序(布局、渲染层基础知识)
  • $NOIp2018$劝退记
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (C++17) std算法之执行策略 execution
  • (C++哈希表01)
  • (二)springcloud实战之config配置中心
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (二十四)Flask之flask-session组件
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (六)Hibernate的二级缓存
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • (转载)虚函数剖析
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据