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

数据结构:带头双向循环链表的实现

引言

单链表存在缺陷:需要从头开始找前一个节点

解决方法:双向链表

链表的结构(8种):

1. 单向,双向

2. 带头、不带头

  • 带头即为带哨兵位的头节点,第一个节点不存储有效数据。
  • 带头节点,不需要改变传过来的指针,也就是意味着不需要传二级指针了,因为不管是头删还是尾删都不会改变头结点的位置,故不用二级指针进行传参。
  • 做好不要用头节点存链表的长度

3. 循环,非循环

之前说的链表里最后一个节点指向空指针,循环链表里最后一个结点指向第一个结点的地址

链表结构可分为单向带头循环,单向不带头循环,将以上三类进行排列组合可得2*2*2=8种链表结构

这里我就说一下带头双向循环链表吧

图示方框为头节点,不添加任何有效数据,头节点的前驱指向3的位置,3的后驱指向头节点,图示就是带头双向循环链表了

我们先来简单实现带头双向循环链表吧

带头双向循环链表的初始化

将头节点的前驱和后驱均指向自己。

typedef double LTDataType;
typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;int data;
}ListNode;
ListNode* ListInit();
//创建一个结点
ListNode* BuyListNode(LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->data = x;newnode->prev = NULL;newnode->next = NULL;return newnode;
}
初始化链表
ListNode* ListInit()
{ListNode* phead = BuyListNode(0);phead->data = phead;phead->prev = phead;return phead;
}

带头双向循环链表的尾插:

双向循环链表可直接通过头节点找到尾节点,

将尾节点的next指向新建节点,

新建节点prev指向最初尾节点,

新建节点的next的指向头节点,

头节点的prev指向新建节点。

//尾插
void ListPushBack(ListNode* phead, LTDataType x) 
{//无论链表是否为空,均可尾插ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);newnode->prev=tail;newnode->next = phead;phead->prev = newnode;}

 带头双向链表的输出:

遍历整个链表,直到遍历到头节点(循环)

void ListPrint(ListNode* phead)
{assert(phead);//phead不能为空ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}

带头双向链表的头删:

记录第一个和第二个节点的位置,

将头节点next指向第二个节点

,第二个节点的prev指向头节点即可完成头删。

void ListPopFront(ListNode* phead, LTDataType x) 
{assert(phead);assert(phead->next!=NULL);//保证无结点时不删除ListNode* first = phead->next;ListNode* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;
}

带头双向链表的头插:

首先要记录第一个节点的位置,以防位置被覆盖

将头节点的next指向新建节点,

新建节点的prev指向头节点,

新建节点的next指向第一个节点,

第一个节点的prev指向新建节点。

void ListPushFront(ListNode* phead, LTDataType x)
{assert(phead);ListNode* first = phead->next;ListNode* newnode = BuyListNode(x);phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;
}

带头双向链表的尾删:

记录左后一个节点以及倒数第二个节点的位置。

将倒数第二个节点的next指向头节点,

头结点的prev指向倒数第二个节点,

释放掉最后一个节点。

//尾删
void ListPopBack(ListNode* phead)
{assert(phead);assert(phead->next != NULL);//不可把头结构删除ListNode* tail = phead->prev;ListNode* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;
}

带头双向循环链表的查找:

 遍历链表直到遍历至头节点,若找到要找的值,就返回该地址,遍历完还没有找到就返回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;}return NULL;
}

在带头双向链表的某个节点前插入新的结点:

记录插入位置的前一个位置,

新建链表的prev指向前一个链表,

前一个链表的next指向新建链表,

新建链表的next指向插入位置

,插入位置的prev指向前一个位置。

// 在pos之前插入x
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* prev = pos->prev;ListNode* newnode = BuyListNode(x);newnode->prev = prev;prev->next = newnode;newnode->next = pos;pos->prev = newnode;
}

 删除带头双向链表的某个结点:

记录删除结点位置的前一个节点位置以及后一个节点的位置

前一个节点的next指向后一个节点,

后一个节点的prev指向前一个节点

释放要删除节点的指针

//删除pos位置的值
void ListErase(ListNode* pos)
{assert(pos);ListNode* prev = pos->prev;ListNode* next = pos->next;prev->next = next;next->prev->prev;free(pos);pos=NULL;
}

释放掉整个链表:

 

遍历整个链表,注意在释放节点时,要先记录下一个节点,遍历完之后,释放头节点。

//释放链表
void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* next = cur->next;free(cur);cur = next;}free(phead);
}

双向带头循环链表的特点,结构复杂,但操作简单

带头双向循环 -- 最优链表结构,任意位置插入删除数据空间复杂度都是0(1)。

相关文章:

数据结构:带头双向循环链表的实现

引言 单链表存在缺陷:需要从头开始找前一个节点 解决方法:双向链表 链表的结构(8种): 1. 单向,双向 2. 带头、不带头 带头即为带哨兵位的头节点,第一个节点不存储有效数据。带头节点&#…...

最小生成树(Minimum Spanning Tree)及生成MST的几种方法

最小生成树 (Minimum Spanning Tree) 最小生成树是图论领域的一个基本概念,适用于加权连通图,其中包括若干顶点(节点)以及连接这些顶点的边(边可以有权重)。在一个加权连通图中,生成树&#xf…...

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计 0x01 前言 在当今互联网的广袤世界中,各式交互平台层出不穷。每一个交互平台几乎都要求用户注册账号,而这些账号则成为我们在数字世界中的身份象征。账号的安全性变得至…...

io基础入门

压缩的封装 参考:https://blog.csdn.net/qq_29897369/article/details/120407125?utm_mediumdistribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-120407125-blog-120163063.235v38pc_relevant_sort_base3&spm1001.2101.3001.…...

k8s ingress 无法找到端点

文章目录 ingress rule无法找到端点这个注解是什么意思呢?为何不生效呢?端点无法更新?如何确认ingressclass呢?修复端点无法发现的问题多个ingress controller 架构 ingress rule无法找到端点 在vnnox-cn集群创建ingress&#xf…...

properties转yml

目前搜索到的大部分代码都存在以下问题: 复杂结构解析丢失解析后顺序错乱 所以自己写了一个,经过不充分测试,基本满足使用。可以直接在线使用 在线地址 除了yml和properties互转之外,还可以生成代码、sql转json等,可…...

谈谈中间件设计的思路

前言 想要设计和真正理解中间件的架构理论和思想。对于开发来说需要具备三个关键的能力 1:基础通用技术的深入理解和运用2:了解和熟悉常见中间件的设计思想,且有自己的感悟,并且能按照自己的理解模仿写一写3:业务的高度理解能力…...

WT2605-24SS音频蓝牙录放语音芯片:标准蓝牙功能与多样化存储播放方式助力音频体验升级

在音频技术日新月异的今天,WT2605-24SS音频蓝牙录放语音芯片以其强大的功能和出色的性能,成为了音频市场的一颗璀璨明星。该芯片不仅具备标准音频蓝牙功能,还支持蓝牙电话本、录音功能以及多种存储和播放方式,为用户提供了更加便捷…...

openssl生成ssl证书

x509证书一般会用到三类文,key,csr,crt。 Key 是私用密钥openssl格,通常是rsa算法。 Csr 是证书请求文件,用于申请证书。在制作csr文件的时,必须使用自己的私钥来签署申,还可以设定一个密钥。…...

以太网PHY,MAC接口

本文主要介绍以太网的 MAC 和 PHY,以及之间的 MII(Media Independent Interface ,媒体独立接口)和 MII 的各种衍生版本——GMII、SGMII、RMII、RGMII等。 简介 从硬件的角度看,以太网接口电路主要由MAC(M…...

c语言中 , x++ 和 ++x的区别

一 c语言中 , x 和 x的区别 x 和 x 是 C 语言中的自增运算符,它们的区别在于它们的执行时机和返回值: 1. x (后缀自增): 先使用变量的值,然后再将变量的值加 1。这意味着,如果你在一个表达式中使用了 x,那么该表达式…...

DBeaver 社区版(免费版)下载、安装、解决驱动更新出错问题

DBeaver 社区版(免费版) DBeaver有简洁版,企业版,旗舰版,社区版(免费版)。除了社区版,其他几个版本都是需要付费的,当然相对来说,功能也要更完善些&#xff…...

景联文科技加入中国人工智能产业联盟(AIIA)数据委员会

近日,景联文科技加入中国人工智能产业联盟(AIIA)数据委员会,成为委员会成员单位。 中国人工智能产业发展联盟(简称AIIA)是在国家发改委、科技部、工信部、网信办指导下,由中国信息通信研究院等单…...

数据结构 / 结构体指针

1. 格式 struct 结构体名{数据类型 成员1;数据类型 成员2; .... };struct 结构体名 *指针变量名 2. 结构体指针指向普通变量的地址 struct CAR{char name[10];int price; };struct CAR car{"byd",160}; struct CAR *p&car; //p是指向结构体变量car的指针// p…...

P1 什么是链表 C语言简单易懂

目录 前言 01 什么是链表 02 数组的特点 03 数组的缺点 3.1 删除数组其中一个元素 3.2 数组增加某个节点 04 链表 前言 🎬 个人主页:ChenPi 🐻推荐专栏1: 《 C 》✨✨✨ 🔥 推荐专栏2: 《 Linux C应用编程(概念…...

Python实现FA萤火虫优化算法优化循环神经网络分类模型(LSTM分类算法)项目实战

说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法(Fire-fly algorithm,FA)由剑桥大学Yang于2009年提出 , …...

Spring Task

Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。 **定位:**定时任务框架 **作用:**定时自动执行某段Java代码 cron表达式 cron表达式其实就是一个字符串,通过cron表达式可以定义任务触…...

HttpServletRequest/Response视频笔记

学习地址:144-尚硅谷-Servlet-HttpServletRequest类的介绍_哔哩哔哩_bilibili 目录 1.HttpServletRequest 类 a.HttpServletRequest类有什么作用 b.HttpServletRequest类的常用方法 c.如何获取请求参数 d.解决post请求中文乱码问题 获取请求的参数值相关问题 …...

网上选课系统源码(Java)

JavaWebjsp网上选课系统源码 运行示意图:...

mac修改默认shell为bash

1. 打开系统偏好设置 2. 点击用户群组 3. 按住ctrl,点击用户名 4. 点击高级选项,修改登录shell 参考:在 Mac 上将 zsh 用作默认 Shell - 官方 Apple 支持 (中国)...

告别系统卡顿:RyTuneX全方位性能优化指南

告别系统卡顿:RyTuneX全方位性能优化指南 【免费下载链接】RyTuneX RyTuneX is a cutting-edge optimizer built with the WinUI 3 framework, designed to amplify the performance of Windows devices. Crafted for both Windows 10 and 11. 项目地址: https://…...

Pixel Aurora Engine部署案例:边缘计算设备(Jetson Orin)轻量化部署

Pixel Aurora Engine部署案例:边缘计算设备(Jetson Orin)轻量化部署 1. 项目背景与价值 Pixel Aurora Engine是一款基于AI扩散模型的创意工具,专为生成复古像素艺术设计。其独特的8-bit游戏风格界面和高效生成能力,使…...

以采购管理系统为例,构建多角色AI智能体协作系统

成果演示(基于 Trae Solo) 1.构建智能体Trae Solo 支持智能生成智能体,输入角色及职能描述,即可得到角色智能体。在此构建需求分析智能体、架构设计智能体、前端智能体、后端智能体进行演示。2.创建任务 本文依照需求分析、架构设…...

OpenCore Legacy Patcher免费教程:3个关键步骤让老Mac焕发新生

OpenCore Legacy Patcher免费教程:3个关键步骤让老Mac焕发新生 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 还在为苹果官方不支持你的老Mac升级…...

Vue项目里嵌入一个专属绘图工具:我是如何用Drawio-Embed定制企业级流程设计器的

Vue项目中定制企业级流程设计器:基于Drawio-Embed的深度集成实践 当企业级应用需要内置可视化流程设计能力时,现成解决方案往往难以满足高度定制化的业务需求。本文将分享如何基于Drawio核心引擎,通过Vue生态实现一个深度集成、可完全定制的流…...

如何快速恢复华硕笔记本色彩配置文件:G-Helper智能修复方案

如何快速恢复华硕笔记本色彩配置文件:G-Helper智能修复方案 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Stri…...

【KS-Downloader】快手无水印内容获取开源工具技术解析

【KS-Downloader】快手无水印内容获取开源工具技术解析 【免费下载链接】KS-Downloader 快手(KuaiShou)视频/图片下载工具;数据采集工具 项目地址: https://gitcode.com/gh_mirrors/ks/KS-Downloader 在短视频内容创作领域&#xff0c…...

英特尔I350网卡PXE功能深度配置:从FLASH状态查询到端口精准控制

1. 英特尔I350网卡PXE功能基础认知 第一次接触服务器网卡PXE配置的朋友可能会觉得这是个"黑盒子"。其实简单来说,PXE(Preboot eXecution Environment)就是让计算机在没装系统的情况下,通过网络启动并安装操作系统的技术…...

除了Omnipeek,你的8812BU网卡还能怎么玩?Win10下的另类WiFi抓包与网络诊断实战

解锁Realtek 8812BU网卡的隐藏潜能:Windows 10下的WiFi抓包与网络诊断全攻略 当你手握一块Realtek 8812BU无线网卡时,可能只把它当作普通的网络连接工具。但实际上,这款硬件在Windows 10环境下可以变身为强大的网络诊断利器。本文将带你探索…...

从机械模型到控制算法:手把手教你用Adams 2020与MATLAB/Simulink搭建第一个联合仿真项目

Adams与Simulink联合仿真入门:零基础实现小球圆周运动控制 当多体动力学仿真遇上控制系统设计,Adams与MATLAB/Simulink的联合仿真能力为工程师打开了全新的可能性。本文将带你从零开始,完成第一个联合仿真项目——控制一个小球实现匀速圆周运…...