链表的基础

 

目录

顺序表

链表

需要注意的 

链表的优势 

 单链表的实现

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.hqwc.cn/news/528023.html

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

相关文章

⭐每天一道leetcode:83.删除排序链表中的重复元素(简单;链表遍历、删除经典题目)

⭐今日份题目 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例1 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例2 输入&#xff1a;head [1,1,2,3,3] 输出&#xff1a;[1,2,3] …

【Lazy ORM】 小工具 acw 本地客户端 你负责点击页面,他负责输出代码

介绍 wu-smart-acw-client 简称acw-client&#xff0c;是一个基于Lazy ORM定制的客户端代码生成小工具 Lazy ORM 小工具 acw 本地客户端 你负责点击页面&#xff0c;他负责输出代码安装 <dependency><groupId>top.wu2020</groupId><artifactId>wu-sma…

C语言自定义类型——结构体(struct)

【本节内容】 1. 结构体类型的声明 2. 结构体变量的创建和初始化 3. 结构体内存对齐 4. 结构体传参 5. 结构体实现位段 1. 结构体类型的声明 struct tag {member-list; }variable-list; 例如描述一个学生&#xff1a; struct Stu {char name[20];//名字int age;//年…

Linux中防火墙相关操作

一、查看防火墙状态 可通过两种方式查看防火墙状态&#xff0c;一种通过systemctl命令&#xff0c;另一种是通过firewall-cmd命令。 1、systemctl status firewalld 2、firewall-cmd --state 二、关闭防火墙 1、暂时关闭&#xff1a;设置暂时关闭防火墙将会在下次重启系统后失…

力扣530. 二叉搜索树的最小绝对差

思路1&#xff1a;中序遍历&#xff0c;递归排序成有序数组&#xff1b;因为是有序&#xff0c;只需要求相邻两个值的最小差值。 class Solution {ArrayList <Integer> list new ArrayList();int ans 100001;//题目最大 100000public int getMinimumDifference(TreeNo…

微信小程序跳转到其他小程序

有两种方式&#xff0c;如下&#xff1a; 一、appid跳转 wx.navigateToMiniProgram({appId: 目标小程序appid,path: 目标小程序页面路径,//不配的话默认是首页//develop开发版&#xff1b;trial体验版&#xff1b;release正式版envVersion: release, success(res) {// 打开成功…

大数据时代的数据保护:分布式存储系统的七大原则

第一原则&#xff1a;“灾”和“备”&#xff0c;区分容灾切换与数据备份的区别 管理对象 管理对象 防什么&#xff1f; 底层逻辑 核心评价指标 容灾切换 IT环境与业 物理灾难 …

登录凭证------

为什么需要登录凭证&#xff1f; web开发中&#xff0c;我们使用的协议http是无状态协议&#xff0c;http每次请求都是一个单独的请求&#xff0c;和之前的请求没有关系&#xff0c;服务器就不知道上一步你做了什么操作&#xff0c;我们需要一个办法证明我没登录过 制作登录凭…

GCN 翻译 - 3

3 SEMI-SUPERVISED NODE CLASSIFICATION 这里简单引入一个例子&#xff0c;利用图上信息传播的方式的一个灵活的模型&#xff0c;我们来解决一个图上节点分类的半监督问题。正如在introduction里面提到的&#xff0c;我们应用数据X和图结构的邻接矩阵锁提出的模型f(X,A)在图结…

鸿蒙Harmony应用开发—ArkTS声明式开发(通用属性:动态属性设置)

动态设置组件的属性&#xff0c;支持开发者在属性设置时使用if/else语法&#xff0c;且根据需要使用多态样式设置属性。 说明&#xff1a; 从API Version 11开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 attributeModifier attributeMo…

免费无水印视频素材哪里下载?这几个地方您要知道

哟哟&#xff0c;切克闹&#xff0c;视频剪辑达人们&#xff0c;是不是在视频素材的海洋里迷航了&#xff1f;别着急&#xff0c;今天我就给大家分享几个超实用的无水印短视频素材合集网&#xff0c;让你的创作更加得心应手&#xff0c;从此素材不再是你的烦恼 1&#xff0c;蛙…

选修-单片机作业第1/2次

第一次作业 第二次作业 1、51 系列单片机片内由哪几个部分组成&#xff1f;各个部件的最主要功能是什么&#xff1f; 51系列单片机的内部主要由以下几个部分组成&#xff0c;每个部件的主要功能如下&#xff1a; 1. **中央处理器&#xff08;CPU&#xff09;**&#xff1a;这是…