链表的基础

news2024/9/29 7:32:06

 

目录

顺序表

链表

需要注意的 

链表的优势 

 单链表的实现

1.单链表的准备

2.单链表的结构体的创建

 3.单链表的准备

 4.前插

5.后插

 6.后删

7.前删

8.任意位置前插

9.任意位置后插

 10.删除

11.修改

12.打印

13.释放链表


 总说链表难,但我感觉只要认真听讲,再加上自己敲敲代码,也不是很难,毕竟后面还有更难的算法  哈哈

顺序表

想要了解什么是链表,我们要先知道什么是顺序表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结 构,常见的线性表:顺序表、链表、栈、队列、字符串...

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物 理上存储时,通常以数组和链式结构的形式存储

 这一点在通讯录的实现给出了充足的运用,然后向更深的探索,也就慢慢产生了链表

链表

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

这就好比火车一样,每个车间都装着东西,然而车间与车间之间并不是向顺序表一样直接加加向后,而是每个车间是通过中间车钩连接起来的,

 在数据结构上的链表也是同样道理,在一个结构体内,有一部分装着必要的信息,而另一部分又有指针,该指针存放着下一个结构体的地址,使得两个结构体如果火车一样连接在一起;

文字表示固然不清楚,我们展示图形:

此处只展示单链表,单链表会的话,双链表也是同样道理,可以自己实现 

需要注意的 

我们的链表最后一个节点的指针部分,必须存放的是NULL这里我们需要自己写代码让其为NULL要不然没有这一步,我们不知道结束的判断是什么 

链表的优势 

这里是摘自别人的博客 

 链表基础知识详解(非常详细简单易懂)-CSDN博客

人家写的比我写的详细多了,还讲解了双链表,值得学习 

 

   链表是通过节点把离散的数据链接成一个表,通过对节点的插入和删除操作从而实现 对数据的存取。而数组是通过开辟一段连续的内存来存储数据,这是数组和链表最大的区 别。数组的每个成员对应链表的节点,成员和节点的数据类型可以是标准的 C 类型或者是 用户自定义的结构体。数组有起始地址和结束地址,而链表是一个圈,没有头和尾之分, 但是为了方便节点的插入和删除操作会人为的规定一个根节点。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/qq_61672347/article/details/125701955

 单链表的实现

1.单链表的准备

我们先写出需要用到的头文件 

#include <stdio.h>
#include <string.h>
#include<malloc.h>
#include<stdlib.h>
#include<assert.h>
#include<errno.h>

typedef int SLDataType;

这里的重命名是为了方便以后修改

2.单链表的结构体的创建

一部分存放需要存的信息,一部分为指针存放下一个结构体的地址

typedef int SLDataType;

typedef struct SLList
{
    SLDataType x;
    struct SLList* next;
}SL;

 3.单链表的准备

int main()
{
	SL* SLList=NULL;
	return 0;
}

 4.前插

前插需要考虑的就是如果单链表本来就没有节点 

大致图:

需要注意的是我们传的是指针的地址,我们需要用二级指针接收,才可以改变一级指针指向的内容

	SLPushFront(&SLList, 5);

    void SLPushFront(SL** pphead, SLDataType x)
{
	assert(pphead);
	SL* newcode = (SL*)malloc(sizeof(SL));
	if (newcode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newcode->next = *pphead;
	newcode->x = x;
	*pphead = newcode;
}

5.后插

 后插跟前插同样的道理

 同样需要考虑的是没有节点的问题与只有一个节点

void SLPushback(SL** pphead,SLDataType x)
{
	assert(pphead);
	SL* newcode = (SL*)malloc(sizeof(SL));
	if (*pphead == NULL)
	{
		*pphead = newcode;
		(*pphead)->x = x;
		(*pphead)->next = NULL;
		return;
	}
	SL* tail = *pphead;
	while (tail->next != NULL)
	{
		tail = tail->next;
	}
	tail->next = newcode;
	tail = tail->next;
	tail->x = x;
	tail->next = NULL;
}

 6.后删

 

后删同样需要考虑没有节点,没有节点当然删不了啊,还有只有一个节点,我们需要直接将这个节点直接释放,然后等于NULL

void SLPopBack(SL** pphead)
{
	assert(pphead);
	assert(*pphead);
	SL* tail = *pphead;
	//一个也没有
	assert(*pphead);
	//一个节点
	if ((*pphead)->next==NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	//多个节点
	while (tail->next->next != NULL)
	{
		tail = tail->next;
	}
	free(tail->next);
	tail->next = NULL;
}

7.前删

void SLPopFront(SL** pphead)
{
	assert(pphead);
	assert(*pphead);
	SL* tail = *pphead;
	*pphead = (*pphead)->next;
	free(tail);//tail是SL* tail=&SLList;
}

8.任意位置前插

 我们需要先找到该位置,然后在与前面前插后插同样方法进行插入

	SL* pos = SLFind(SLList,2);
	SLInsert(&SLList,pos,20);//前插
	SLPrint(SLList);
SL* SLFind(SL* pphead, SLDataType x)
{
	assert(pphead);
	SL* tail = pphead;
	while (tail->x != x)
	{
		tail = tail->next;
	}
	return tail;
}

void SLInsert(SL** pphead, SL* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	SL* newcode = (SL*)malloc(sizeof(SL));
	if (newcode == NULL)
	{
		perror("SLInsert fail");
	}
	while (tail->next != pos)
	{
		tail = tail->next;
	}
	newcode->next = tail->next;
	newcode->x = x;
	tail->next = newcode;
}

9.任意位置后插

	SL* pos = SLFind(SLList,2);
    SLInsertBack(&SLList, pos, 30);//后插
	SLPrint(SLList);
void SLInsertBack(SL** pphead, SL* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	SL* newcode = (SL*)malloc(sizeof(SL));
	if (newcode == NULL)
	{
		perror("SLInsertBack fail");
	}
	while (tail != pos)
	{
		tail = tail->next;
	}
	newcode->next = tail->next;
	newcode->x = x;
	tail->next = newcode;
}

 10.删除

	SL* pos = SLFind(SLList,2);

	SLErase(&SLList, pos);
	SLPrint(SLList);
void SLErase(SL** pphead, SL* pos)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	if (pos == *pphead)
	{
		SLPopFront(pphead);
		return;
	}
	while (tail->next != pos)
	{
		tail = tail->next;
	}
	tail->next = pos->next;
	free(pos);
}

11.修改

	pos= SLFind(SLList, 3);
	SLModify(&SLList, pos, 50);
	SLPrint(SLList);
void SLModify(SL** pphead, SL* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);
	SL* tail = *pphead;
	while (tail != pos)
	{
		tail = tail->next;
	}
	tail->x = x;
}

12.打印

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

13.释放链表

void SLList_free(SL** pphead)
{
	//定义一个指针变量保存头结点的地址
	SL* pb = *pphead;
	while (*pphead != NULL)
	{
		//先保存p_head指向的结点的地址
		pb = *pphead;
		//p_head保存下一个结点地址
		*pphead = (*pphead)->next;
		free(pb);
		pb = NULL;
	}
}

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

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

相关文章

10.网络文件系统( NFS)使用

网络文件系统&#xff08; NFS&#xff09; 使用 NFS 优点&#xff1a; 开发过程中不受开发板空间的限制&#xff0c;直接使用网络文件就像使用本地文件一样&#xff1b;调试过程中避免一一将编译后的应用程序和库文件复制到开发板上。 在开发板中使用网络文件系统可以为开发和…

python并发编程:异步IO(Asynchronous I/O)

异步IO(Asynchronous I/O) Linux下的asynchronous IO其实用得不多&#xff0c;从内核2.6版本才开始引入。先看一下它的流程&#xff1a; 用户进程发起read操作之后&#xff0c;立刻就可以开始去做其它的事。而另一方面&#xff0c;从kernel的角度&#xff0c;当它受到一个asyn…

Python实现ETS指标平滑模型(ETSModel算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 ETS模型&#xff08;Error-Trend-Seasonality Model&#xff09;&#xff0c;是一种广泛应用于时间序列…

蓝桥杯第一天

这题就是典型的位数贡献大于数量贡献&#xff0c; 1花的火柴更少&#xff0c;所以尽量用完10个1&#xff0c;然后其实就是简单的背包问题尽量拿最多的物品&#xff08;数字&#xff09;&#xff0c;限重为300&#xff0c;各物品&#xff08;数字&#xff09;的重量即为所需火柴…

数学建模-敏感度分析(美赛)

从多个不确定性因素中逐一找出对投资项目经济效益指标有重要影响的敏感性因素&#xff0c;并分析、测算其对项目经济效益指标的影响程度和敏感性程度&#xff0c;进而判断项目承受风险的能力。若某参数的小幅度变化能导致经济效益指标的较大变化&#xff0c;则称此参数为敏感性…

1572.矩阵对角线元素的和

刷算法题&#xff1a; 第一遍&#xff1a;1.看5分钟&#xff0c;没思路看题解 2.通过题解改进自己的解法&#xff0c;并且要写每行的注释以及自己的思路。 3.思考自己做到了题解的哪一步&#xff0c;下次怎么才能做对(总结方法) 4.整理到自己的自媒体平台。 5.再刷重复的类…

车载诊断协议DoIP系列 —— 传输层控制协议(TCP)用户数据报协议(UDP)

车载诊断协议DoIP系列 —— 传输层控制协议(TCP)&用户数据报协议(UDP) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师(Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎…

C++ 买卖股票问题

目录 买卖股票的最佳时机 买卖股票的最佳时机III 买卖股票的最佳时机 IV 买卖股票的最佳时机 II 买卖股票的最佳时机含手续费 买卖股票的最佳时机含冷冻期 买卖股票的最佳时机 121. 买卖股票的最佳时机 buy&#xff1a;手上有股票的最大收益 sell&#xff1a;手上没有股票…

蓝桥杯备战刷题five(自用)

1.数字三角形&#xff08;方向次数限制&#xff0c;动态规划&#xff09; //如果n为奇数时&#xff0c;最后必然走到最后行最中间的数&#xff0c;如果为偶数&#xff0c;则取中间两个数的最大值&#xff0c; //因为向左下走的次数与向右下走的次数相差不能超过 1 #include …

图腾柱PFC工作原理:一张图

视屏链接&#xff1a; PFC工作原理

centos7中python3.10找不到openssl解决方案

如果有用其他方法安装了其他版本openssl&#xff0c;记得卸载其他的openssl&#xff0c;删除其他的openssl相关文件。 yum remove openssl* rm -rf ***下载最新版的openssl文件 按照官网安装方法安装openssl 官方安装地址https://docs.python.org/3/using/unix.html#on-linu…

智慧城市与智慧乡村:共创城乡一体化新局面

一、引言 随着科技的不断进步和城乡发展的日益融合&#xff0c;智慧城市与智慧乡村的建设已成为推动城乡一体化发展的新引擎。智慧城市利用物联网、大数据、云计算等先进技术&#xff0c;实现城市治理、公共服务、产业发展等领域的智能化&#xff1b;而智慧乡村则借助现代科技…

中国电子学会2021年9月份青少年软件编程Sc ratch图形化等级考试试卷四级真题

【 单选题 】 1.下面哪个选项程序可以交换下图列表中第2项和第3项的位置&#xff1f; A&#xff1a; B&#xff1a; C&#xff1a; D&#xff1a; 2.雷峰塔景区的门票价格政策是&#xff1a;成人40元/人&#xff1b;6周岁&#xff08;含6周岁&#xff09;以下的实行免票&#…

【AI视野·今日NLP 自然语言处理论文速览 第八十三期】Wed, 6 Mar 2024

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 6 Mar 2024 Totally 74 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers MAGID: An Automated Pipeline for Generating Synthetic Multi-modal Datasets Authors Hossein Aboutalebi, …

springboot260火锅店管理系统

火锅店管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装火锅店管理系统软件来发挥其高效…

ESP8266开发板 + DHT11+远程开关+ThingsCloud+APP+QQ邮件推送告警

ESP32 是乐鑫公司推出的 WiFi 芯片&#xff0c;它不仅支持 WiFi 和 BLE&#xff0c;还可以作为可编程的 MCU&#xff0c;通过 Espressif IDF、Arduino 等框架编写固件&#xff0c;用于非常广泛的物联网场景。 这个教程我们分享如何在 Arduino IDE 中使用 ThingsCloud ESP SDK&…

MIT6.828LAB4 (3)

LAB3_Part B: Copy-on-Write Fork 文章目录 LAB3_Part B: Copy-on-Write Fork前言练习8练习9练习10练习11练习12总结 前言 记录一下自己的学习过程 实验内容翻译&#xff1a; https://gitee.com/cherrydance/mit6.828 该翻译仅供参考 练习8 实现sys_env_set_pgfault_upcall系统…

10-ARM gicv3/gicv4的总结-基础篇

目录 1、gic的版本2、GICv3/gicv4的模型图3、gic中断号的划分4、GIC连接方式5、gic的状态6、gic框架7、gic Configuring推荐 本文转自 周贺贺&#xff0c;baron&#xff0c;代码改变世界ctw&#xff0c;Arm精选&#xff0c; armv8/armv9&#xff0c;trustzone/tee&#xff0c;s…

LeetCode刷题日志-17.电话号码的字母组合

纯暴力解法&#xff0c;digits有多长&#xff0c;就循环多少次进行字母组合 class Solution {public List<String> letterCombinations(String digits) {List<String> reslut new ArrayList<>();if(digits.equals(""))return reslut;Map<Inte…

C语言程序与设计——函数(二)递归练习

在上一篇文章中接触到了递归这种编程方法&#xff0c;下面我们将用几个程序加深以下对递归的理解。 递归实际上就是程序调用自身的编程技巧 递归程序的组成&#xff1a; 边界条件处理针对于问题的处理过程和递归过程结果返回 二分查找 首先分析二分查找的查找逻辑&#xff1a; …