当前位置: 首页 > news >正文

看完书上的链表还不会实现?不进来看看?

1.1链表的概念

定义:

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

特点:

链表由一系列节点组成,节点在运行时动态生成 (malloc),每个节点包括两个部分:

一个是存储数据元素的数据域

另一个是存储下一个节点地址的指针域

如图:

1.2链表的概述

链表作为 C 语言中一种基础的数据结构,在平时写程序的时候用的并不多,但在操作系统里面使用的非常多。不管是RTOS还是Linux等使用非常广泛,所以必须要搞懂链表,链表分为单向链表和双向链表,单向链表很少用,使用最多的还是双向链表。单向链表懂了双向链表自然就会了。

1.3单向不带头不循环的链表的初始化

参数的传入:涉及改变链表的操作统统用指针传链表(其中特别注意的是需要改变传入的头结点时需要传入二级指针)不然函数调用完成之后,为传入的链表分配的的内存会自动释放,链表不会有任何改变。创建头结点,为头结点分配内存。

令头节点的指针为空指针(指针不初始化容易出现很多问题)

PS:这里为什么要动态分配内存呢?

因为线性表的顺序存储结构用数组实现,而数组占用的是一整块内存,数组元素分布很集中,需要提前预定数组的长度。而链表是一种动态结构,它所占用的大小和位置是不需要提前分配的,可以根据自身的需求即时生成。

第二步:创建第二个节点,将其放在第一个节点的后面(第一的节点的指针域保存第二个节点的地址)

第三步:再次创建节点,找到原本链表中的最后一个节点,接着讲最后一个节点的指针域保存新节点的地址,以此内推。

1.4单链表的一些操作

1.4.1链表的遍历

1.输出第一个节点的数据域,输出完毕后,让指针保存后一个节点的地址

2.输出移动地址对应的节点的数据域,输出完毕后,指针继续后移

3.以此类推,直到节点的指针域为NULL。

1.4.2链表的查找

// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x) {assert(plist);SListNode* cur = plist;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

1.4.3链表的头插头删,尾插尾删


// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{if (*pplist == NULL){SListNode* newnode = BuySListNode(x);*pplist = newnode;}else{SListNode *newnode = BuySListNode(x);newnode->next=*pplist;*pplist = newnode;}
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{assert(*pplist);if ((*pplist)->next == NULL)//对结构体指针的地址传值时访问该结构体的成员先得对结构体地址解引用{SListNode* cur = *pplist;//直接free(*pplist),会使得pplist被置为随机值free(cur);*pplist = NULL;}else{SListNode *cur = *pplist;*pplist = (*pplist)->next;//左右两边的星号都不要漏。free(cur);}
}// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{if (*pplist == NULL){SListNode* newnode = BuySListNode(x);*pplist = newnode;}else{SListNode* tail = *pplist;SListNode* newnode = BuySListNode(x);while (tail->next){tail = tail->next;}tail->next = newnode;}
}
// 单链表的尾删
void SListPopBack(SListNode** pplist) {assert(*pplist);SListNode* tail=*pplist,*prev=*pplist;if (tail->next == NULL){free(tail);*pplist = NULL;}else {while (tail->next){prev = tail;tail = tail->next;}prev->next = NULL;free(tail);tail = NULL;}
}

1.4.4单链表的插入

// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?因为找pos之前的位置需要O(n)的时间复杂度
void SListInsertAfter(SListNode* pos, SLTDateType x) {assert(pos);SListNode* newnode = BuySListNode(x);newnode->next = pos->next;pos->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos) {assert(pos&&pos->next);SListNode* next = pos->next;pos->next = next->next;free(next);next = NULL;
}

// 单链表在pos位置之后插入x

// 分析思考为什么不在pos位置之前插入?

因为找pos之前的位置需要O(n)的时间复杂度进行查找到pos的前一个元素

1.4.5链表节点的删除

如果链表为空,不需要删除

如果删除的是第一个结点,则需要将保存链表首地址的指针保存第一个结点的下一个结点的 地址

如果删除的是中间结点,则找到中间结点的前一个结点,让前一个结点的指针域保存这个结 点的后一个结点的地址即可

// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos) {assert(pos&&pos->next);SListNode* next = pos->next;pos->next = next->next;free(next);next = NULL;
}

1.4.6单链表的销毁

重新定义一个指针q,保存p指向节点的地址,然后p后移保存下一个节点的地址,然后释放q对应的节点,以此类推,直到p为NULL为止。

// 单链表的销毁
void SListDestroy(SListNode* plist) {while (plist){SListNode* next = plist;free(plist);plist = next;}
}

1.5双向带头不循环的链表

虽然听起来复杂,但其实只是结构复杂,但是遍历还是增删查改插入和删除等都是十分简单的

#include"List.h"ListNode* BuyListNode(int x)
{ListNode* new = (ListNode*)malloc(sizeof(ListNode));new->data = x;new->next = NULL;new->prev = NULL;return new;
}
// 创建返回链表的头结点.
ListNode* ListCreate(void)
{ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));newhead->next = newhead;newhead->prev = newhead;return newhead;
}
// 双向链表销毁
void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead;while (cur){ListNode* next = cur->next;free(cur);cur = next;}
}
// 双向链表打印
void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* tail = pHead->prev;ListNode* new = BuyListNode(x);new->next = tail->next;tail->next->prev = new;new->prev = tail;tail->next = new;
}
// 双向链表尾删
//需要注意此处如果链表初始化后不断删除会使得pHead指针指向的地方不确定,如果后续用户未重新创造双向链表的哨兵位而继续插入数据,会导致非法访问。
//或者加个条件判断判断是否只有一个哨兵位,是的话就不再进行删除。
void ListPopBack(ListNode* pHead)
{assert(pHead);ListNode* tail = pHead->prev;tail->prev->next= tail->next;//左边修改的是指针域,右边是具体的链表的位置。tail->next->prev = tail->prev;free(tail);//tail = NULL;
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{ListInsert(pHead->next, x);
}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;if (cur != pHead){pHead->next = cur->next;cur->next->prev = pHead;free(cur);}cur = NULL;
}
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x) {assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){if (cur->data == x){return cur;}cur = cur->next;}if (cur == pHead){return NULL;}
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x) {assert(pos);ListNode *new=BuyListNode(x);ListNode* prev = pos->prev;new->next = pos;pos->prev = new;new->prev = prev;prev->next = new;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos) {ListNode* prev = pos->prev;prev->next = pos->next;pos->next->prev = prev;free(pos);}

着重注意这段

// 双向链表尾删

//需要注意此处如果链表初始化后不断删除会使得pHead指针指向的地方不确定,如果后续用户未重新创造双向链表的哨兵位而继续插入数据,会导致非法访问。

//或者加个条件判断判断是否只有一个哨兵位,是的话就不再进行删除。

void ListPopBack(ListNode* pHead)

{

assert(pHead);

ListNode* tail = pHead->prev;

tail->prev->next= tail->next;//左边修改的是指针域,右边是具体的链表的位置。

tail->next->prev = tail->prev;

free(tail);

//tail = NULL;

}

相关文章:

看完书上的链表还不会实现?不进来看看?

1.1链表的概念定义:链表是一种物理存储上非连续,数据元素的逻辑顺序通过链表中的指针链接次序,实现的一种线性存储结构。特点:链表由一系列节点组成,节点在运行时动态生成 (malloc),…...

【批处理脚本】-3.2-call命令详解

"><--点击返回「批处理BAT从入门到精通」总目录--> 共5页精讲(列举了所有call的用法,图文并茂,通俗易懂) 在从事“嵌入式软件开发”和“Autosar工具开发软件”过程中,经常会在其集成开发环境IDE(CodeWarrior,S32K DS,Davinci,EB Tresos,ETAS…)中,…...

华为OD机试题,用 Java 解【寻找相同子串】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

思腾合力深思系列 | 四款高性能 AI 服务器

深思系列 AI 服务器涵盖多种 CPU 平台&#xff0c;支持按客户需求预装 OS、驱动、DL 框架、常用 DL 库&#xff0c;节省您大量的前期调试时间&#xff0c;开机即用。 一个简单的任务&#xff0c;若想要在 AI 的脑中形成清晰的思路&#xff0c;需要大量的实验和练习。从 AI 训练…...

Vue3做出B站【bilibili】 Vue3+TypeScript+ant-design-vue【快速入门一篇文章精通系列(一)前端项目案例】

本项目分为二部分 1、后台管理系统&#xff08;用户管理&#xff0c;角色管理&#xff0c;视频管理等&#xff09; 2、客户端&#xff08;登录注册、发布视频&#xff09; Vue3做出B站【bilibili】 Vue3TypeScriptant-design-vue【快速入门一篇文章精通系列&#xff08;一&…...

2.3操作系统-进程管理:死锁、死锁的产生条件、死锁资源数计算

2.3操作系统-进程管理&#xff1a;死锁、死锁的产生条件、死锁资源数计算死锁死锁的产生条件死锁资源数计算死锁 进程管理是操作系统的核心&#xff0c;如果设计不当&#xff0c;就会出现死锁的问题。如果一个进程在等待意见不可能发生的事&#xff0c;进程就会死锁。而如果一…...

人物百科怎么建?个人百度百科创建的注意事项

百科词条根据百科类型可分为人物词条、品牌词条以及企业词条等等,对于不同类型的词条,在创建时有着不同的规则要求。 相对于品牌词条和企业词条&#xff0c;人物词条是相对有难度的一类&#xff0c;因为品牌有注册商标&#xff0c;企业有营业执照&#xff0c;都是比较容易佐证的…...

ArrayList与LinkedList的区别 以及 链表理解

list接口中ArrayList、LinkedList都不是线程安全&#xff0c;Vector是线程安全 1、数据结构不同 ArrayList是Array(动态数组)的数据结构&#xff0c;LinkedList是Link(链表)双向链表的数据结构。 2、空间灵活性 ArrayList最好指定初始容量 LinkedList是比ArrayList灵活的&a…...

电脑蓝屏怎么办?这5个技巧你必须学会

案例&#xff1a;电脑蓝屏是什么原因&#xff1f;怎么样可以解决&#xff1f; “救命&#xff01;&#xff01;&#xff01;电脑是怎么了&#xff1f;开机直接蓝屏&#xff0c;是哪里坏了吗&#xff1f;前几天电脑还是好的&#xff0c;今早一打开就是蓝屏&#xff0c;可能是之…...

大数据 | (三)centos7图形界面无法执行yum命令

大家好&#xff0c;今天是三八女神节了&#xff01; 你知道吗&#xff1f;世界上第一位电脑程序设计师是名女性&#xff0c;Ada Lovelace (1815-1852)。 她是一位英国数学家兼作家&#xff0c;第一位主张计算机不只可以用来算数的人&#xff0c;也发表了第一段分析机用的演算…...

历史上被发现的第一个真正的Bug - Grace Hopper

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…...

KiCad 编译

KiCad 编译 因为最新项目需要&#xff0c;所以看了一下KiCad的编译&#xff0c;这里介绍的是64位电脑的编译&#xff0c;32位小伙伴请绕道官网看教程呦。 您可以在KiCad内查看基本的编译教程。 我这里也是参考的官网编译教程进行的编译&#xff0c;接下来让我们一起看看吧。…...

HTML 简介

文章目录HTML 简介实例解析什么是HTML?HTML 标签HTML 元素Web 浏览器HTML 网页结构HTML版本<!DOCTYPE> 声明通用声明HTML5HTML 4.01XHTML 1.0中文编码HTML 简介 HTML 实例 <!DOCTYPE html> <html><head><meta charset"utf-8"><ti…...

2023浙江省赛“信息安全管理与评估“--数字取证调查--网络数据包分析解析(高职组)

2022全国职业技能大赛“信息安全管理与评估”(高职组)任务书 2022全国职业技能大赛“信息安全管理与评估”任务书第一阶段竞赛项目试题第二阶段竞赛项目试题任务 2: 网络数据包分析第三阶段竞赛项目试题2022全国职业技能大赛“信息安全管理与评估”任务书 第一阶段竞赛项目…...

【Redis应用】查询缓存相关问题解决(二)

&#x1f697;Redis应用学习第二站~ &#x1f6a9;起始站&#xff1a;【Redis应用】基于Redis实现共享session登录(一) &#x1f6a9;本文已收录至专栏&#xff1a;Redis技术学习 &#x1f44d;希望您能有所收获&#xff0c;底部附有完整思维导图 一.概述 本篇我们会一起来学习…...

【SpringCloud】SpringCloud教程之Nacos实战(三集群配置)

目录前言一.Nacos集群逻辑图二.Nacos集群搭建1.搭建数据库&#xff0c;初始化数据库表结构2.下载Nacos3.配置Nacos3.启动Nacos4.配置启动nginx5.测试是否成功6.设置服务的nacos地址7.新增一个配置&#xff0c;查看数据看是否进行持久化了前言 在我前面两篇讲的都是单个nacos&a…...

什么是激励能力?HR人才测评

什么是激励能力&#xff1f;激励能力主要是针对管理型岗位而言的&#xff0c;尤其是团队型管理&#xff0c;既要督导团队成员&#xff0c;更需要掌握激励下属的方法和技巧。在HR人才测评系统中&#xff0c;对于管理型岗位的人才测评指标&#xff0c;通常也会包含激励能力&#…...

【刷题笔记】之滑动窗口(长度最小的子数组、水果成篮、最小的覆盖子串)

滑动窗口模板//滑动窗口模板&#xff1a;注意使用滑动窗口方法&#xff0c;使用一个 for(while) 循环中的变量是用来控制终止位置的//最小滑窗&#xff1a;给定数组 nums&#xff0c;定义滑动窗口的左右边界 i、j&#xff0c;求满足某个条件的滑窗的最小长度 for(j 0; j < …...

【JavaScript速成之路】JavaScript函数

&#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f525;系列专栏&#xff1a;【JavaScript速成之路】 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; 文章目录前言1&#xff0c;函数基础1.1&#xff0c;函数概念1.2&#xff0c;函数使用1.3&…...

萤火虫算法优化SVM变压器故障分类预测,fa-svm分类预测,libsvm参数优化

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 SVM应用实例,基于fa-svm分类预测 代码 结果分析 展望 支持向量机SVM的详细原理 SVM的定义 支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是…...

STM32串口环形队列实现与优化

## 1. STM32串口环形队列实现方案### 1.1 环形队列数据结构设计环形队列&#xff08;Ring Buffer&#xff09;是嵌入式系统中处理串口数据流的经典方案&#xff0c;其核心数据结构定义如下&#xff1a;c #define RING_BUFF_SIZE 256 // 根据实际需求调整缓冲区大小typedef str…...

uConfigLib:嵌入式轻量级类型安全配置注册表

1. uConfigLib 库深度解析&#xff1a;面向嵌入式系统的轻量级配置注册表实现1.1 设计目标与工程定位uConfigLib 是一个专为资源受限嵌入式平台设计的纯 C 语言配置管理库&#xff0c;其核心目标并非提供通用键值存储&#xff0c;而是构建一种类 Windows 注册表&#xff08;Reg…...

Arduino Mega硬件PWM舵机库:绕过Software Delay实现±0.5μs高精度控制

1. 项目概述Servo Hardware PWM是一款专为 Arduino/Genuino Mega 系列开发板设计的高性能舵机控制库。其核心目标是绕过软件定时与通用 I/O 抽象层&#xff0c;直接利用 ATmega2560 微控制器内置的 16 位硬件定时器/计数器&#xff08;Timer3、Timer4、Timer5&#xff09;生成精…...

AI原生前端:基于OpenTiny NEXT生态的全链路学习、实战、开源实践与行业前瞻

过去二十年&#xff0c;前端行业经历了四次决定性的进化浪潮&#xff1a;第一次是Web1.0时代&#xff0c;jQuery等工具库终结了原生JS的兼容乱象&#xff0c;让前端从静态页面的拼接者&#xff0c;变成了动态交互的实现者&#xff1b;第二次是三大框架的崛起&#xff0c;Vue、R…...

DataX 实战:从零部署到多场景数据同步

1. DataX入门&#xff1a;为什么选择它作为数据同步工具 第一次接触DataX是在三年前的一个紧急项目里&#xff0c;当时需要把生产环境的MySQL数据实时同步到分析库。试过几种方案后&#xff0c;最终被DataX的稳定性和灵活性打动。作为阿里开源的数据同步工具&#xff0c;它最大…...

终极指南:掌握Starlight文档导航自定义排序的7个高级技巧

终极指南&#xff1a;掌握Starlight文档导航自定义排序的7个高级技巧 【免费下载链接】starlight &#x1f31f; Build beautiful, accessible, high-performance documentation websites with Astro 项目地址: https://gitcode.com/gh_mirrors/st/starlight Starlight是…...

CK3M多轴运动控制器实战:EtherCAT总线伺服系统从零配置全解析

1. CK3M控制器与EtherCAT系统初识 第一次接触CK3M多轴运动控制器时&#xff0c;我完全被它强大的功能震撼到了。这款控制器就像工业自动化领域的"大脑"&#xff0c;能够同时协调多个伺服电机精准运动。而EtherCAT总线技术则是连接这个大脑与各个执行机构&#xff08;…...

YOLOv9官方镜像快速入门:三步完成图片检测,支持自定义数据集训练

YOLOv9官方镜像快速入门&#xff1a;三步完成图片检测&#xff0c;支持自定义数据集训练 1. 环境准备与快速部署 YOLOv9官方训练与推理镜像已经预装了完整的深度学习开发环境&#xff0c;包含所有必要的依赖项。这意味着你不需要手动安装Python、CUDA或PyTorch&#xff0c;也…...

手把手教你用KVM在openEuler 22.03 LTS上安装华为FusionCompute 6.5.1 CNA(含VNC避坑指南)

深度实战&#xff1a;在openEuler 22.03 LTS上通过KVM部署FusionCompute CNA全流程解析 当企业需要构建私有云环境时&#xff0c;华为FusionCompute作为成熟的虚拟化平台常被列为首选方案。本文将完整呈现如何在openEuler 22.03 LTS系统中&#xff0c;通过KVM虚拟化技术实现Fus…...

GPU友好型部署!Nanbeige 4.1-3B Streamlit WebUI显存优化实测教程

GPU友好型部署&#xff01;Nanbeige 4.1-3B Streamlit WebUI显存优化实测教程 想在自己的电脑上跑一个好看又好用的AI对话应用&#xff0c;是不是总被复杂的部署步骤和巨大的显存占用劝退&#xff1f;今天&#xff0c;我就带你实测一个专为Nanbeige 4.1-3B模型打造的Streamlit…...