【数据结构】04.单链表

一、链表的概念及结构

概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
在这里插入图片描述
节点的组成主要有两个部分:当前节点要保存的数据和保存下⼀个节点的地址(指针变量)。

补充说明:
1.链式机构在逻辑上是连续的,在物理结构上不⼀定连续
2、节点⼀般是从堆上申请的
3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续

二、单链表的实现

2.1节点的定义

typedef int SLDataType;
//定义链表结构体
typedef struct SList
{SLDataType data;//数据域struct SList* next;//指针域
}SL;

2.2单链表的打印

void SLPrint(SL** pphead)
{SL* cur = *pphead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

2.3单链表的增删查改

这里由于申请结点使用较多,我们将其封装为一个函数。

//获得新节点
SL* SListBuynode(SLDataType x)
{SL* newnode = (SL*)malloc(sizeof(SL));if (newnode == NULL){perror("SListBuyNode is failed");return 1;}newnode->data = x;newnode->next = NULL;return newnode;
}
//尾插
void  SLPushBack(SL** pphead, SLDataType x)
{assert(pphead);SL* newnode = SListBuynode(x);//链表没有元素时if (*pphead == NULL){*pphead = newnode;return;}//链表有元素时SL* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;
}//尾删
void SLPopBack(SL** pphead)
{assert(*pphead);assert(pphead);//删除的时头结点if ((*pphead)->next==NULL){free(*pphead);*pphead = NULL;return;}//删除的不是头结点SL* cur_tail = *pphead;SL* cur = NULL;while (cur_tail->next){cur = cur_tail;cur_tail = cur_tail->next;}cur->next = NULL;free(cur_tail);cur_tail = NULL;
}//头插
void SLPushFront(SL** pphead, SLDataType x)
{assert(pphead);SL* newnode = SListBuynode(x);newnode->next = *pphead;*pphead = newnode;
}//头删
void SLPopFront(SL** pphead)
{assert(pphead);assert(*pphead);SL* cur_head = (*pphead)->next;free(*pphead);*pphead = cur_head;
}//查找
SL* SLFind(SL** pphead, SLDataType x)
{assert(pphead);SL* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//任意位置之前插入
void SLInsert(SL** pphead, SL* pos, SLDataType x)
{assert(pphead);assert(*pphead);assert(pos);SL* newnode = SListBuynode(x);//pos是头结点if (*pphead == pos){newnode->next = *pphead;*pphead = newnode;return;}//pos不是头结点 SL* cur = *pphead;while (cur->next != pos){cur = cur->next;}newnode->next =pos;cur->next = newnode;
}//指定位置之后插入
void SLInsertAfter(SL* pos, SLDataType x)
{assert(pos);SL* newnode = SListBuynode(x);newnode->next = pos->next;pos->next = newnode;
}//任意位置删除
void SLErase(SL** pphead, SL* pos)
{assert(pphead);assert(*pphead);assert(pos);//pos是头结点if (*pphead == pos){SL* newhead = (*pphead)->next;free(*pphead);*pphead = NULL;*pphead = newhead;return;}//pos不是头结点SL* cur = *pphead;while (cur->next != pos){cur = cur->next;}cur->next = pos->next;free(pos);pos = NULL;
}//删除指定位置之后的元素
void SLEraseAfter(SL* pos)
{assert(pos);assert(pos->next);SL* cur = pos->next;pos->next = cur->next;free(cur);cur = NULL;}

2.4单链表的销毁

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

2.5 单链表的源代码

//SingleList.h
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLDataType;typedef struct SList
{SLDataType data;struct SList* next;
}SL;void SLPrint(SL** pphead);//打印void  SLPushBack(SL** pphead, SLDataType x);//尾插
void SLPopBack(SL** pphead);//尾删void SLPushFront(SL**  pphead, SLDataType x);//头插
void SLPopFront(SL** pphead);//头删void SLInsert(SL** pphead, SL* pos, SLDataType x);//指定位置之前插入
void SLInsertAfter( SL* pos, SLDataType x);//指定位置之后插入SL* SLFind(SL** pphead, SLDataType x);//查找void SLErase(SL** pphead, SL* pos);//指定位置元素删除
void SLEraseAfter(SL* pos);//删除指定位置之后的元素 void SLDestroy(SL** pphead);//销毁链表
//SingleList.c#define _CRT_SECURE_NO_WARNINGS #include"SL.h"void SLPrint(SL** pphead)
{SL* cur = *pphead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}SL* SListBuynode(SLDataType x)//获得新节点
{SL* newnode = (SL*)malloc(sizeof(SL));if (newnode == NULL){perror("SListBuyNode is failed");return 1;}newnode->data = x;newnode->next = NULL;return newnode;
}void  SLPushBack(SL** pphead, SLDataType x)//尾插
{assert(pphead);SL* newnode = SListBuynode(x);if (*pphead == NULL){*pphead = newnode;return;}SL* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;
}void SLPopBack(SL** pphead)//尾删
{assert(*pphead);assert(pphead);if ((*pphead)->next==NULL){free(*pphead);*pphead = NULL;return;}SL* cur_tail = *pphead;SL* cur = NULL;while (cur_tail->next){cur = cur_tail;cur_tail = cur_tail->next;}cur->next = NULL;free(cur_tail);cur_tail = NULL;
}void SLPushFront(SL** pphead, SLDataType x)//头插
{assert(pphead);SL* newnode = SListBuynode(x);newnode->next = *pphead;*pphead = newnode;
}void SLPopFront(SL** pphead)//头删
{assert(pphead);assert(*pphead);SL* cur_head = (*pphead)->next;free(*pphead);*pphead = cur_head;
}SL* SLFind(SL** pphead, SLDataType x)//查找
{assert(pphead);SL* cur = *pphead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}void SLInsert(SL** pphead, SL* pos, SLDataType x)//任意位置插入
{assert(pphead);assert(*pphead);assert(pos);SL* newnode = SListBuynode(x);if (*pphead == pos)//pos是头结点{newnode->next = *pphead;*pphead = newnode;return;}//pos不是头结点 SL* cur = *pphead;while (cur->next != pos){cur = cur->next;}newnode->next =pos;cur->next = newnode;
}void SLInsertAfter(SL* pos, SLDataType x)//指定位置之后插入
{assert(pos);SL* newnode = SListBuynode(x);newnode->next = pos->next;pos->next = newnode;
}void SLErase(SL** pphead, SL* pos)//任意位置删除
{assert(pphead);assert(*pphead);assert(pos);//pos是头结点if (*pphead == pos){SL* newhead = (*pphead)->next;free(*pphead);*pphead = NULL;*pphead = newhead;return;}//pos不是头结点SL* cur = *pphead;while (cur->next != pos){cur = cur->next;}cur->next = pos->next;free(pos);pos = NULL;
}void SLEraseAfter(SL* pos)//删除指定位置之后的元素
{assert(pos);assert(pos->next);SL* cur = pos->next;pos->next = cur->next;free(cur);cur = NULL;}void SLDestroy(SL** pphead)//销毁链表
{SL* cur = *pphead;while (cur){SL* next = cur->next;free(cur);cur = NULL;cur = next;}*pphead = NULL;
}

三、链表的分类

链表的结构非常多样,以下情况组合起来就有8种(2x2x2)链表结构:
在这里插入图片描述
在这里插入图片描述

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:单链表和双向带头循环链表

  1. 无头单向非循环链表:结构简单,⼀般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
  2. 带头双向循环链表:结构最复杂,⼀般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

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

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

相关文章

nginx重定向

nginx的重定向 location 匹配 location 匹配的就是后面的URI /wordpress location 匹配的分类和优先级** 1、精确匹配 location / 对字符串进行完全匹配&#xff0c;必须完全符合 2、正则匹配 ^~ 前缀匹配&#xff0c; 以什么开头 -区分大小写的匹配 ~*不区分大小写 …

数字化精益生产系统--MES制造管理系统

MES制造管理系统&#xff08;Manufacturing Execution System&#xff09;是现代制造企业中至关重要的管理工具&#xff0c;它集合了软件与多种硬件设备&#xff0c;形成了一个综合智能化系统&#xff0c;对从原材料上线到成品入库的整个生产过程进行实时数据采集、控制和监控。…

java 基础之 反射技术_java 程序src阶段 class对象阶段 run阶段3个阶段

System.out.println(in); } publicClass[] aa1(String name, int[] password){ returnnew Class[]{String.class} ; } privatestatic void aa1(int num){ System.out.println(num“静态方法”); } public static void main(String[] args){ System.out.println(“main”…

香港即将“放松”加密货币监管!加密牌照制度备受批评!全球主力军无法进入香港市场?动摇了香港Web3的信心!

2024年7月3日&#xff0c;香港金融服务及库务局局长许正宇在立法会会议上表示&#xff0c;香港金融管理局(HKMA)和证券及期货事务监察委员会(SFC)将根据市场发展情况&#xff0c;适时检讨虚拟资产相关活动的监管要求。 这一表态引发了人们对香港加密货币监管框架可能进行调整的…

超详细的 C++中的封装继承和多态的知识总结<1.封装与继承>

引言 小伙伴们都知道C面向对象难&#xff0c;可是大家都知道&#xff0c;这个才是C和C的真正区别的地方&#xff0c;也是C深受所有大厂喜爱的原因&#xff0c;它的原理更接近底层&#xff0c;它的逻辑更好&#xff0c;但是学习难度高&#xff0c;大家一定要坚持下来呀&#xff…

起飞,纯本地实时语音转文字!

简介 偶然在 github 上翻到了这个项目 https://github.com/k2-fsa/sherpa-ncnn 在没有互联网连接的情况下使用带有 ncnn 的下一代 Kaldi 进行实时语音识别。支持 iOS、Android、Raspberry Pi、VisionFive2、LicheePi4A等。 也就是说语音转文字可以不再借助网络服务的接口&am…

mac显示隐藏的.git文件

打开终端 输入命令 defaults write com.apple.finder AppleShowAllFiles YES killall Finder

Python代码设置Excel工作表背景色或背景图

Excel是工作中数据处理和分析数据的重要工具。面对海量的数据和复杂的表格&#xff0c;如何提高工作效率、减少视觉疲劳并提升数据的可读性是不容忽视的问题。而给工作表设置合适的背景是表格优化的一个有效方式。为Excel工作表设置背景色或背景图不仅能够美化工作表&#xff0…

25.labview数据采集中的读取和写入文本文件和Excel表格文件

①本文将会讲解labview读取和写入文本文件和Excel文件的几种不同方式&#xff0c;讲解程序的基本原理&#xff0c;并提出具体的实施方案&#xff0c;本文内容如下所示。 ②本文文章结束会提供大家 文本和表格读取写入的源程序 &#xff0c;以便于大家学习和使用。 本文中可能用…

TYPE-C转DC转接头方案,ECP5701支持5V、9V、12V、15V、20V电压输出

如今随着这几年的USB-C PD适配器的普及&#xff0c;消费者手上的PD适配器越来越普遍&#xff0c;如何让以前的电源适配器也可以用上PD适配器呢&#xff1f;如此一来以前的电源适配器坏了&#xff0c;就不需要费心费力的寻找相同的适配器进行更换&#xff0c;甚至于只能将整个设…

Xilinx FPGA:vivado关于单端ROM的一个只读小实验

一、实验要求 将生成好的voe文件里的数据使用rom读取出来&#xff0c;采用串口工具发送给电脑&#xff08;当按键来临时&#xff09;。 二、程序设计 按键消抖模块&#xff1a; timescale 1ns / 1ps module key_debounce(input sys_clk ,input rst_n…

怎么录制电脑内部声音?好用的录音软件分享,看这篇就够了!

如何录制电脑内部声音&#xff1f;平时使用电脑工作&#xff0c;难免会遇到需要录音的情况。好用的录音软件有很多&#xff0c;也有部分录屏工具也支持录音功能。 那么如何录制电脑内部声音呢&#xff1f;本文整理了几个录制电脑内部声音的方法&#xff0c;如果你需要在电脑上录…

Spring框架的学习SpringMVC(1)

1.什么是MVC (1)MVC其实就是软件架构的一种设计模式&#xff0c;它将软件的系统分为&#xff0c;&#xff08;视图&#xff0c;模型&#xff0c;控制器&#xff09;三个部分 1.1View(视图) 视图也就是&#xff0c;在浏览器显示的那一个部分&#xff0c;是后端数据的呈现 1.…

推荐一个私有化部署的物联网平台

引言 随着物联网技术的飞速发展&#xff0c;越来越多的企业开始寻求能够提供稳定、安全、可定制的物联网解决方案。私有化部署的物联网平台因其能够满足企业对数据安全和个性化需求的优势&#xff0c;逐渐成为市场的新宠。本文将详细介绍ThingsKit物联网平台&#xff0c;一个专…

常见问题记录

conda操作 conda精确查找某个包的版本 conda list 包名下载源 -i https://pypi.mirrors.ustc.edu.cn/simple/conda查看下载源 conda config --show channels下载torch conda install pytorch1.13.0 torchvision0.14.0 torchaudio0.13.0 cpuonlyconda环境没有名字 利用vsc…

【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven+文档 前后端可分离也可不分离

目录 1项目功能 2项目介绍 3项目地址 1项目功能 【java计算机毕设】美容院管理系统 项目源代码MySQL springboot vue html maven文档 前后端可分离也可不分离 2项目介绍 系统功能&#xff1a; 美容院管理系统包括管理员、用户俩种角色。 管理员功能包括个人中心模块用于修改…

“第六感”真的存在吗?

现在已有证据表明&#xff0c;人类除视觉、听觉、嗅觉、味觉和触觉五种感觉以外&#xff0c;确实存在“第六感” “第六感”的学术名称为“超感自知觉”(简称ESP)&#xff0c;它能透过正感官之外的渠道接收信息&#xff0c; 预知将要发生的事&#xff0c;而且与当事人之前的经…

向量数据库、主键存储引擎、高速网络 RDMA 框架……DolphinDB 版本更新啦!

盛夏已至&#xff0c;炎热的七月伊始&#xff0c;DolphinDB 也迎来了版本的更新。此次更新的 3.00.1 与 2.00.13 版本从多个维度进行了优化扩展&#xff0c;进一步深化了 DolphinDB 在机器学习、数据分析等领域的尝试与探索。 为了响应用户日益增长的 AI 运算需求&#xff0c;…

C语言自定义类型(结构体,枚举,联合):

大家好久不见&#xff0c;今天我们来学习一下C语言中的自定义类型&#xff1a; C语言的自定义类型包括&#xff1a;结构体&#xff0c;枚举和联合&#xff0c;接下来大家跟我来一起认识一下这三种类型。 目录 1. 结构体 1.1.1 结构体类型的声明 1.1.2 结构的特殊声明 1.1…

钡铼RTU无线S270用于风力发电站机房远程状态监测和故障预警系统集成

在现代风力发电行业中&#xff0c;机房的远程监测和故障预警系统对于保障风力发电机组的稳定运行至关重要。钡铼第4代S270工业级4G远程遥测终端&#xff08;RTU&#xff09;&#xff0c;以其先进的技术和多功能应用&#xff0c;成为风力发电站机房智能化管理的理想选择。 技术…