链表之单链表

上一篇博客我们学习了线性表中的顺序表,这一篇博客让我们继续往下了解线性表的链表,链表分为好几种结构,活不多说,让我们开始学习吧!


目录

1.链表

2.链表的结构

3.单链表的实现


1.链表

1.概念:它是一种物理存储结构上非连续非顺序的存储结构,数据元素的逻辑顺序是通过链                表中的指针链接次序实现的。它在空间上,按需给空间,不要求物理空间的连续,                和顺序表不同,它头部和中间的数据的插入就不需要挪动数据。链表的实现是通过                指针的。

2.有些老铁可能不明白什么是物理结构,它就是在内存中实实在在的存储形式。

什么是不连续非顺序,我们画图来给大家解释一下:

在这些节点中间,我们可以插入新的节点,又是新的地址,所以说它不是按顺序走的。这些节点在内存中,可能这有一个节点,也可能那有一个节点,但它们彼此之间通过指针相连接,只要指针不断,就可以找到下一个节点。

3.链表只能一个一个诶个访问,只能从头找,因为一旦它找到下一个节点,它就不知道上一个节点的位置了(双向链表可以找到上一个,我们到了那个章节在继续学习)。这时,又显示出顺序表的好处了,因为它可以直接定位到要查找数据的位置,但是它会造成空间的浪费,所以说有好有坏,需要大家自己体会。

2.链表的结构

链表分为八种结构,在这里先给大家一个总体的框架,方便接下来的学习:

单链表,双链表,不带头链表,带头链表,循环链表,不循环链表,这六种链表构成了链表的八种结构,分别是:

1.单向不带头不循环链表

2.单向不带头循环链表

3.单向带头不循环链表

4.单向带头循环链表

5.双向不带头不循环链表

6.双向不带头循环链表

7.双向带头不循环链表

8.双向带头循环链表

我们今天在这里会实现第一种结构,单向不带头不循环链表,相信通过这个链表的实现,大家可以把2,3,4种结构都实现。

3.单链表的实现

现在我们来实现这个单链表,可以类比顺序表写,这一部分的代码都大差不差,具体要看怎么实现。

SList.h文件

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int ALTDataType;//创建结构体,用来创建链表组成元素
typedef struct SListNode
{ALTDataType data;//链表数据struct SListNode* next;//链表指向下一个元素的指针,指向下一个节点的位置
}SLN;//开辟空间来存入数据
SLN* BuySListNode(ALTDataType x);
//打印链表
void SListPrint(SLN* phead);
//头插
void sListPushFront(SLN** pphead, ALTDataType x);
//尾插
void sListPushBack(SLN** pphead, ALTDataType x);
//头删
void sListPopFront(SLN** pphead);
//尾删
void sListPopBack(SLN** pphead);
//查找链表
SLN* sListFind(SLN* phead, ALTDataType x);
//修改对应链表位置的数据
void sListModify(SLN* phead, SLN* pos, ALTDataType x, ALTDataType y);
//任意位置的插入,在pos位置的前一个位置插入
void sListInsert(SLN** pphead, SLN* pos, ALTDataType x);
//任意位置的删除
void sListErase(SLN** pphead, SLN* pos);
//销毁链表
void destorySList(SLN* phead);

SList.c文件

#include"SList.h"//开辟空间来存入数据
SLN* BuySListNode(ALTDataType x)
{SLN* newnode = (SLN*)malloc(sizeof(SLN));if (newnode == NULL){perror("malloc");return NULL;}newnode->data = x;newnode->next = NULL;return newnode;
}//打印链表
void SListPrint(SLN* phead)
{assert(phead);SLN* cur = phead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("\n");
}//头插
//想要头插,我们要把新节点的地址给到头节点,再把新节点定义为新的头节点
void sListPushFront(SLN** pphead, ALTDataType x)
{SLN* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}//尾插
void sListPushBack(SLN** pphead, ALTDataType x)
{SLN* newnode = BuySListNode(x);//若一开始链表为空,我们直接插入一个新节点if (*pphead == NULL){*pphead = newnode;}//我们要创建一个变量,找到链表的尾端,从尾端插入SLN* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = newnode;//尾节点链接新节点
}//头删
void sListPopFront(SLN** pphead)
{assert(*pphead);SLN* next = (*pphead)->next;//*小于->的优先级,编译器不通过free(*pphead);*pphead = NULL;*pphead = next;
}
//尾删
void sListPopBack(SLN** pphead)
{assert(*pphead);//当只有一个节点时if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}SLN* tail = *pphead;SLN* prev = NULL;while (tail->next){prev = tail;tail = tail->next;}free(tail);tail = NULL;prev->next = NULL;
}
//查找链表
SLN* sListFind(SLN* phead, ALTDataType x)
{assert(phead);SLN* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}
//修改对应链表位置的数据
void sListModify(SLN* phead, SLN* pos, ALTDataType x, ALTDataType y)
{pos = sListFind(phead, x);pos->data = y;
}
//任意位置的插入,在pos位置的前一个位置插入
void sListInsert(SLN** pphead, SLN* pos, ALTDataType x)
{if (pos == *pphead){sListPushFront(pphead, x);return;}SLN* newnode = BuySListNode(x);SLN* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;
}
//任意位置的删除,删除pos位置的值
void sListErase(SLN** pphead, SLN* pos)
{if (pos == *pphead){sListPopFront(pphead);return;}SLN* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;
}
//销毁链表,这些空间,我们要一个一个释放,防止内存泄漏
void destorySList(SLN* phead)
{assert(phead);SLN* tail = phead->next;while (tail){SLN* next = tail->next;free(tail);tail = NULL;tail = next;}free(phead);phead = NULL;
}

test.c文件

#include"SList.h"void Test1()
{SLN* plist = NULL;SLN* pos = NULL;sListPushFront(&plist, 4);sListPushFront(&plist, 3);sListPushFront(&plist, 2);sListPushFront(&plist, 1);SListPrint(plist);sListPushBack(&plist, 5);sListPushBack(&plist, 6);sListPushBack(&plist, 7);sListPushBack(&plist, 8);SListPrint(plist);sListPopFront(&plist);sListPopFront(&plist);SListPrint(plist);sListPopBack(&plist);sListPopBack(&plist);SListPrint(plist);pos = sListFind(plist, 5);if (pos == NULL){printf("找不到该数据\n");}else{printf("已找到该数据,现在进行修改\n");sListModify(plist, pos, 5, 50);}SListPrint(plist);pos = sListFind(plist, 50);if (pos == NULL){printf("找不到该数据\n");}else{printf("已找到该数据,现在进行在pos前插入数据\n");sListInsert(&plist, pos, 20);}SListPrint(plist);pos = sListFind(plist, 20);if (pos == NULL){printf("找不到该数据\n");}else{printf("已找到该数据,现在进行对pos位置数据的删除\n");sListErase(&plist, pos);}SListPrint(plist);destorySList(plist);printf("链表已销毁\n");
}
int main()
{Test1();return 0;
}

结果:大家下去还是要自己敲一遍代码,才能做到掌握


好了,今天的内容就是这些,我们下期再见铁汁们!

感谢品读!!!

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

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

相关文章

大创项目推荐 深度学习 python opencv 火焰检测识别 火灾检测

文章目录 0 前言1 基于YOLO的火焰检测与识别2 课题背景3 卷积神经网络3.1 卷积层3.2 池化层3.3 激活函数&#xff1a;3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV54.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 数据集准备5.1 数…

HTML - 请你谈一谈 iframe的优缺点

难度级别:中级及以上 提问概率:50% iframe是一个HTML标签,它可以在一个网页中嵌入另外一个网页,甚至是把其他的网站嵌入进来。在之前的很长时间里,内部管理系统都在使用iframe,做为菜单切换的主体模板区域框架。iframe包含一个src属性,…

php运行python脚本失败怎么解决

假设有文件&#xff1a;php_test.php python_test.py 在php文件中运行Python&#xff1a; exec("python python_test.py", $array, $ret); 如果运行Python出错并不能保存在数组array中&#xff0c;因此应该把标准错误重定向到文件中&#xff0c;以上代码改写如下&a…

【芯片验证】通关寄存器与ral_model —— 寄存器生成流程中加入backdoor后门配置

前言 【芯片验证】通关寄存器与ral_model —— backdoor后门访问实操测试-CSDN博客 上一篇文章中,我们通过在环境中配置后门路径的方式来实现了寄存器的后门访问,但是在实际应用中,无论寄存器RTL文件、例化还是寄存器模型大概率都是工具生成的,比如在本专栏中实现的gen_r…

Docker实战教程 第2章 Docker基础

3-1 Docker介绍 什么是Docker 虚拟化&#xff0c;容器 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&…

自动驾驶中各种坐标系辨析

坐标系辨析 0. 地球椭圆体1. 大地坐标系2. eci地心惯性坐标系3. 地心地固坐标系(ECEF坐标系&#xff0c;E系)4. 站心坐标系(ENU坐标系)5. UTM坐标系6. LTM坐标系7. IMU坐标系8. 代码部分8.1 LLA(大地坐标系坐标、经纬度海拔)坐标转LTM系(ENU系)下的三维笛卡尔坐标8.2 LLA坐标转…

线上线下陪玩,APP小程序H5。源码交付,支持二开!

线下陪玩的风险与管理方式 1、陪玩者的身心健康风险 线下陪玩的模式决定了陪玩者需要与不同的需求方见面&#xff0c;并满足他们的陪伴和娱乐需求。这种工作方式可能会给陪玩者带来身心上的压力和负担。因为陪玩者需要面对各种需求方的要求&#xff0c;有时还需要虚拟出一种完…

HTML - 你知道b与strong标签的区别吗

难度级别&#xff1a;初级及以上 提问概率&#xff1a;50% 不单单是初学者&#xff0c;即便是有好几年工作经验的前端开发工作者&#xff0c;也会有一大部分人把这两个标签搞混&#xff0c;甚至在工作中&#xff0c;很大一部人不会使用这两个标…

212 基于matlab的双稳态随机共振的算法

基于matlab的双稳态随机共振的算法&#xff0c;分析信噪比随系统参数a,b及乘性噪声和加性噪声的增益变化曲线&#xff0c;60个数据样本可供选择。程序已调通&#xff0c;可直接运行。 212 双稳态随机共振 信噪比增益变化曲线 - 小红书 (xiaohongshu.com)

浅谈分布式光伏电站的运维管理

摘要&#xff1a;随着近些年我国对节能降耗关注力度的持续加大&#xff0c;为满足人们不断增长的电能需求&#xff0c;光伏发电产业得到迅猛发展&#xff0c;其中分布式光伏发电的比重持续增长。在打赢脱贫攻坚战的大背景下&#xff0c;国家电网公司探索出一条“阳光扶贫”的扶…

Spring Cloud微服务入门(一)

微服务的演变过程 //controller 视图交互层 前端数据处理传给service //1.DAO RequestBody userDAO String id;String type; {"id":"lcs", "type":"lcs"} //2.GET请求 findUserById&#xff1f;id1&typelcsRequestParam String …

5.3.1 配置交换机 SSH 管理和端口安全

5.3.1 实验1:配置交换机基本安全和 SSH管理 1、实验目的 通过本实验可以掌握&#xff1a; 交换机基本安全配置。SSH 的工作原理和 SSH服务端和客户端的配置。 2、实验拓扑 交换机基本安全和 SSH管理实验拓扑如图所示。 交换机基本安全和 SSH管理实验拓扑 3、实验步骤 &a…

全面的Docker快速入门教程(详细)

前言&#xff1a; 都2024年了&#xff0c;你还在为了安装一个开发或者部署环境、软件而花费半天的时间吗&#xff1f;你还在解决开发环境能够正常访问&#xff0c;而发布测试环境无法正常访问的问题吗&#xff1f;你还在为持续集成和持续交付&#xff08;CI / CD&#xff09;工…

flink1.18源码本地调试环境

01 源码本地调试环境搭建 1. 从github拉取源码创建本地项⽬ https://github.com/apache/flink.git 可以拉取github上官⽅代码 https://github.com/apache/flink.git GitHub - apache/flink: Apache Flink 2. 配置编译环境 ctrlaltshifts &#xff08;或菜单&#xff09;打…

OpenHarmony Neptune开发板-MQTT连接华为IoT平台

本示例将演示如何在Neptune开发板上使用MQTT协议连接华为IoT平台,使用的是ATH20温湿度传感器模块与Neptune开发板 本示例实现AHT20温湿度数据上报华为IoT平台,IoT平台下发命令控制LED灯的开关 使用W800 SDK功能包中libemqtt来实现连接华为IoT平台 程序设计 初始化 一、MQT…

上位机图像处理和嵌入式模块部署(qmacvisual亮度检测)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们说过&#xff0c;在机器视觉当中&#xff0c;对于光源的处理要非常小心。这里面不仅包括了选择什么样的光源&#xff0c;还取决于怎样使用…

WPF文本框TextEdit不以科学计数法显示

WPF文本框TextEdit不以科学计数法显示 一个float或者double类型的数值&#xff0c;如果小数点后0的个数≥4&#xff0c;在界面上就会自动以科学计数法显示&#xff0c; 比如&#xff1a;0.00003会显示成这样 但是很多时候我并不希望它这样显示&#xff0c;因为这样不方便编辑…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单视频处理实战案例 之一 简单视频放大抖动效果 一、简单介绍 二、简单视频放大抖动效果实现原理 三、简单视频放大…

C# WPF编程-命令

C# WPF编程-命令 概述WPF命令模型ICommand接口RoutedCommand类RoutedUICommand类命令库 概述 使用路由事件可以响应广泛的鼠标和键盘事件&#xff0c;这些事件是低级的元素。在实际应用程序中&#xff0c;功能被划分成一些高级的任务。这些任务可通过各种不同的动作和用户界面…

Spring Boot 学习(2)——HelloWorld

HelloWorld&#xff01;全宇宙码农的第一个&#xff08;行&#xff09;程序&#xff08;代码&#xff09;。 1、创建项目 打开idea&#xff0c;新建一个maven项目。 1&#xff09;选择项目sdk&#xff08;本例是1.8&#xff09; 2&#xff09;输入GroupId&#xff08;co…