链表的基础

 

目录

顺序表

链表

需要注意的 

链表的优势 

 单链表的实现

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.mzph.cn/news/735525.shtml

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

相关文章

1572.矩阵对角线元素的和

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

(南京观海微电子)——Gamma调试

1.什么是Gamma&#xff1f; Gamma的概念源自于CRT响应曲线&#xff0c;最开始是用于反映显像管的图像亮度与输入电子枪的信号电压之间&#xff0c;非线性关系的一个参数。对于CRT显示器而言&#xff0c;电子流大小影响显示的图像亮度大小&#xff0c;而电子流大小与输入电压间…

力扣每日一题 找出数组的第 K 大和 小根堆 逆向思维(TODO:二分+暴搜)

Problem: 2386. 找出数组的第 K 大和 文章目录 思路复杂度&#x1f496; 小根堆&#x1f496; TODO&#xff1a;二分 暴搜 思路 &#x1f468;‍&#x1f3eb; 灵神题解 复杂度 时间复杂度: 添加时间复杂度, 示例&#xff1a; O ( n ) O(n) O(n) 空间复杂度: 添加空间复杂…

【最新版】ChatGPT/GPT4科研应用与AI绘图论文写作(最新增加Claude3、Gemini、Sora、GPTs技术及AI领域中的集中大模型的最新技术)

2023年随着OpenAI开发者大会的召开&#xff0c;最重磅更新当属GPTs&#xff0c;多模态API&#xff0c;未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义&#xff0c;不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

使用 Python 读取 NetCDF 数据

栅格通用数据格式(NetCDF)通常用于存储多维地理数据。这些数据的一些示例包括温度、降水量和风速。NetCDF 中存储的变量通常每天在大片(大陆)区域进行多次测量。由于每天进行多次测量,数据值会快速积累并且变得难以处理。当每个值还分配给一个地理位置时,数据管理会更加复…

springboot257基于SpringBoot的中山社区医疗综合服务平台

中山社区医疗综合服务平台的设计与实现 摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;居民信息因为其管理内容繁杂&#xff0c;管…

Solidity Uniswap V2 价格预言机

预言机是连接区块链与链下服务的桥梁&#xff0c;这样就可以从智能合约中查询现实世界的数据。Chainlink 是最大的oracle网络之一&#xff0c;创建于 2017 年&#xff0c;如今已成为许多 DeFi 应用的重要组成部分。https://github.com/XuHugo/solidityproject Uniswap 虽然是链…

Unity 使用HyBirdCLR调用Newtonsoft.json报错问题

查了老半天&#xff0c;原来是这里的问题 官方解释 解释&#xff1a; 在Unity的IL2CPP Code Generation中&#xff0c;"Faster runtime"和"Faster (smaller) builds"是两种不同的优化设置选项&#xff0c;它们分别影响着运行时性能和构建大小。下面是它们…

最顶级的Unity团队都在使用的技巧!!!

作为该系列的第二篇文章&#xff0c;今天将给大家分享一下&#xff0c;Unity最资深的团队是如何设置物理、UI和音频的。希望可以帮助大家最大限度的使用Unity引擎。 第一篇给大家介绍了如何提高资源、项目配置和图形的性能&#xff0c;感兴趣的朋友千万不要错过了。 文章链接…

关于playbook中when条件过滤报The conditional check ‘result|failed‘ failed的问题

问题现象 在使用plabook中的when做过滤脚本如下&#xff1a; --- - hosts: realserversremote_user: roottasks:- name: Check if httpd service is runningcommand: systemctl status httpdregister: resultignore_errors: True- name: Handle failed service checkdebug:ms…

【运维】本地部署Gemma模型(图文)

工具简介 我们需要使用到两个工具&#xff0c;一个是Ollama&#xff0c;另一个是open-webui。 Ollama Ollama 是一个开源的大语言平台&#xff0c;基于 Transformers 和 PyTorch 架构&#xff0c;基于问答交互方式&#xff0c;提供大语言模型常用的功能&#xff0c;如代码生…

js 【详解】异步

为什么需要使用异步&#xff1f; 减少等待时间&#xff1a;异步编程允许程序在等待某些操作&#xff08;如网络请求或文件读取&#xff09;完成时继续执行其他任务&#xff0c;而不是空等&#xff0c;这样可以显著减少等待时间。提高响应速度&#xff1a;由于JavaScript是单线程…

【Web】浅聊Java反序列化之C3P0——URLClassLoader利用

目录 前言 C3P0介绍 回归本源——序列化的条件 利用链 利用链分析 入口——PoolBackedDataSourceBase#readObject 拨云见日——PoolBackedDataSourceBase#writeObject 综合分析 EXP 前言 这条链最让我眼前一亮的就是对Serializable接口的有无进行了一个玩&#xff0c…

Mybatis-plus连接多数据源操作(SQLServer、MySQL数据库)

Mybatis-plus连接多数据源操作&#xff08;SQLServer、MySQL数据库&#xff09; 一、依赖二、yml配置文件三、业务类四、测试 一、依赖 <!--mybatis多数据源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spri…

采用 Amazon DocumentDB 和 Amazon Bedrock 上的 Claude 3 构建游戏行业产品推荐

前言 大语言模型&#xff08;LLM&#xff09;自面世以来即展示了其创新能力&#xff0c;但 LLM 面临着幻觉等挑战。如何通过整合外部数据库的知识&#xff0c;检索增强生成&#xff08;RAG&#xff09;已成为通用和可行的解决方案。这提高了模型的准确性和可信度&#xff0c;特…

Autosar教程-Mcal教程-GPT配置教程

3.3GPT配置、生成 3.3.1 GPT配置所需要的元素 GPT实际上就是硬件定时器,需要配置的元素有: 1)定时器时钟:定时器要工作需要使能它的时钟源 2)定时器分步:时钟源进到定时器后可以通过分频后再给到定时器 定时器模块选择:MCU有多个定时器模块,需要决定使用哪个定时器模块作…

21-Java观察者模式 ( Observer Pattern )

Java备忘录模式 摘要实现范例 观察者模式 ( Observer Pattern ) 常用于对象间存在一对多关系时&#xff0c;比如&#xff0c;当一个对象被修改时&#xff0c;需要自动通知它的依赖对象 观察者模式属于行为型模式 摘要 1. 意图 定义对象间的一种一对多的依赖关系&#xff…

给 spyter/all-spark-notebook 添加scala支持

spyter/all-spark-notebook默认没有安装scala notebook&#xff0c;需要手动添加。 你可以创建一个新的 Dockerfile&#xff0c;在其中添加你需要的配置和组件。以下是一个简单的例子&#xff1a; FROM jupyter/all-spark-notebook:x86_64-ubuntu-22.04 #冒号后可以是latest&a…

【漏洞复现】锐捷网络NBR700G 信息泄露

0x01 产品简介 锐捷网络NBR700G路由器是锐捷网络股份有限公司的一款无线路由设备。 0x02 漏洞概述 锐捷网络NBR700G路由器存在信息漏洞。未授权的攻击者可以通过该漏洞获取敏感信息。 0x03 测绘语句 fofa&#xff1a;body"系统负荷过高&#xff0c;导致网络拥塞&…

Mint_21.3 drawing-area和goocanvas的FB笔记(六)

FreeBASIC gfx 基本 graphics 绘图 一、旧故事 DOS时代PC技术将各类硬插卡限制在 640K到1MB的空间范围内&#xff0c;BIOS负责在相关位置写读测试卡的存在&#xff0c;那时期的Color Video在0xB800&#xff0c;Monochrome Video在0xB000&#xff0c;这是显卡的内存地址&#…