双链表的实现(数据结构)

链表总体可以分为三大类

一、无头和有头

二、单向和双向

三、循环和不循环

   从上面分类得知可以组合成8种不同类型链表,其中单链表最为简单,双联表最为复杂,两种链表都实现后其余链表都不成问题。

  我们前期博客已将完成了单向无头不循环链表(单链表)的实现,本期博客我们实现双向有头循环链表的实现。

————————————————————————————

说明:

  因为此双链表有头结点,(头结点不存储任何有效数据,双链表中只有头结点时为空链表)

  因此我们无需修改头结点的地址,只需要改变头结点中前驱指针和后面指针的指向即可,所以传参时只需要传头结点的地址即可。

代码实现:

List.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int LTDataType;typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;LTDataType data;
}LTNode;//void LTInit(LTNode** pphead);
LTNode* LTInit();
void LTDestroy(LTNode* phead);//为了保持接口一致性,需要在外部将phead置空。//保留头节点其他的删去
void LTClear(LTNode* phead);
LTNode* BuyNode(LTDataType x);void LTPrint(LTNode* phead);
bool LTEmpty(LTNode* phead);//判断是否为空void LTPushBack(LTNode* phead, LTDataType x);
void LTPopBack(LTNode* phead);void LTPushFront(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);
//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x);
void LTErase(LTNode* pos);LTNode* LTFind(LTNode* phead, LTDataType x);

List.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"LTNode* LTInit()
{LTNode* phead = BuyNode(-1);return phead;
}LTNode* BuyNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->prev = newnode->next = newnode;newnode->data = x;return newnode;
}void LTDestroy(LTNode* phead)
{//哨兵位不能为空assert(phead);LTNode* pcur = phead->next;while (pcur!=phead){LTNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;
}
//清除链表的内容
void LTClear(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}phead->next = phead;phead->prev = phead;
}
void LTPrint(LTNode* phead)
{//链表不能为空assert(phead);LTNode* pcur = phead->next;while (pcur!=phead){printf("%d->",pcur->data);pcur = pcur->next;}printf("\n");
}
bool LTEmpty(LTNode* phead)
{if (phead->next = phead){return true;}else{return false;}
}void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyNode(x);LTNode* ptail = phead->prev;ptail->next = newnode;newnode->prev = ptail;newnode->next = phead;phead->prev = newnode;
}
void LTPopBack(LTNode* phead)
{assert(phead);//链表不能为空assert(phead->next!=phead);LTNode* ptail = phead->prev;LTNode* prev = ptail->prev;phead->prev = prev;prev->next = phead;free(ptail);ptail = NULL;
}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyNode(x);LTNode* next = phead->next;phead->next = newnode;newnode->prev = phead;newnode->next = next;next->prev = newnode;}
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);LTNode* pos = phead->next;LTNode* next = pos->next;phead->next = next;next->prev = phead;free(pos);pos = NULL;
}
//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = BuyNode(x);LTNode* next = pos->next;//pos newnode nextpos->next = newnode;newnode->prev = pos;newnode->next = next;next->prev = newnode;
}
void LTErase(LTNode* pos)
{assert(pos);LTNode* prev = pos->prev;LTNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* pcur = phead->next;while (pcur->data!=x && pcur!=phead){pcur = pcur->next;}if (pcur->data == x){return pcur;}else{return NULL;};
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"int main()
{LTNode* phead = LTInit();if(LTEmpty(phead)){printf("链表为空\n");}LTPushBack(phead,1);LTPushBack(phead,2);LTPushBack(phead,3);LTPushBack(phead,4);LTPrint(phead);LTPopBack(phead);LTPopBack(phead);LTPrint(phead);LTPopFront(phead);LTPrint(phead);LTPushFront(phead,100);LTPushFront(phead,200);LTPushFront(phead,300);LTPrint(phead);LTNode* ret= LTFind(phead,200);if (ret){LTErase(ret);}else{printf("未找到,无法删除\n");}LTPrint(phead);LTNode* ret2 = LTFind(phead, 2);if (ret2){LTInsert(ret2, 3);}else{printf("未找到,无法插入\n");}LTPrint(phead);LTDestroy(phead);phead = NULL;return 0;
}

这个博客如果对你有帮助,给博主一个免费的点赞就是最大的帮助

欢迎各位点赞,收藏和关注哦

如果有疑问或有不同见解,欢迎在评论区留言哦

后续我会一直分享双一流211西北大学软件(C,数据结构,C++,Linux,MySQL)的学习干货以及重要代码的分享

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

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

相关文章

基于PHP的景点数据分析系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 关键理论与技术 3 1.1 框架技术 3 1.1.1 QueryList 3 1.1.2 ThinkPHP 3 1.1.3 Amaze UI 3 1.2 数据可视化技术 4 1.3 数据库技术 4 1.4 本章小结 4 2 需求分析 5 2.1 业务流程分析 5 2.2 功能需求分析 5 2.3 用例分析 7 2.4 非功能性需求…

it-tools工具箱

it-tools 是一个在线工具集合&#xff0c;包含各种实用的开发工具、网络工具、图片视频工具、数学工具等 github地址&#xff1a;https://github.com/CorentinTh/it-tools 部署 docker run -d --name it-tools --restart unless-stopped -p 8080:80 corentinth/it-tools:lat…

gradle 相关

aar 不加 aar 以及 transitive true library可以通过多种格式上传到远程仓库&#xff0c;比如大部分情况下用到的.jar或.aar。当没有指定后缀的话&#xff0c;依赖的时候将会下载它的默认格式&#xff08;由上传方定义&#xff0c;如果没有定义则默认为.jar&#xff09;的Lib…

yolov8多batch推理,nms后处理

0. 背景 在高速公路监控视频场景下&#xff0c;图像分辨率大都是1920 * 1080或者2560 * 1440&#xff0c;远处的物体&#xff08;车辆和行人等&#xff09;都比较小。考虑需要对图像进行拆分&#xff0c;然后把拆分后的数据统一送入模型中&#xff0c;推理的结果然后再做nms&am…

redis centos7 单点搭建

redis centos 安装步骤 下载源文件编译Redis拷贝编译后文件修改配置文件启动redis 下载源文件 wget https://download.redis.io/redis-stable.tar.gz编译Redis tar -xzvf redis-stable.tar.gz cd redis-stable make如果编译成功&#xff0c;你会在src目录中找到几个 Redis 二…

Android Selinux详解[一]---整体介绍

Android 使用安全增强型 Linux (SELinux) 对所有进程强制执行强制访问控制 (MAC)&#xff0c;甚至包括以 Root/超级用户权限运行的进程&#xff08;Linux 功能&#xff09;。 借助 SELinux&#xff0c;Android 可以更好地保护和限制系统服务、控制对应用数据和系统日志的访问、…

【微前端乾坤】 vue2主应用、vue2+webpack子应用,vue3+webpack子应用、vue3+vite子应用的配置

因公司需求 需要将原本vue2iframe 形式的项目改成微前端乾坤的方式。 之前iframe都是直接嵌套到vue2项目的二级目录或者三级目录下的(反正就是要随处可嵌) 用乾坤的原因&#xff1a; 1、iframe嵌套的方式存在安全隐患&#xff1b; 2、项目是联合开发的&#xff0c; 乾坤的方便…

Doris画像存储实践系列二

上一篇: Doris画像存储系列一(https://editor.csdn.net/md/?articleId120416295) 六、画像宽表bitmap倒排表 重复一下bitmap倒排表的优点和缺点 标签类型标签值user_ids性别男1,2性别发3 优点: doris bitmap聚合表在对做用户画像群体计算时很友好,交集/并集/差集因为数据…

SQL23 统计每个学校各难度的用户平均刷题数

题解 | #统计每个学校各难度的用户平均刷题数# 题意明确&#xff1a; 计算每个学校用户不同难度下的用户平均答题题目数 问题分解&#xff1a; 限定条件&#xff1a;无&#xff1b;每个学校&#xff1a;按学校分组group by university不同难度&#xff1a;按难度分组group b…

Hack The Box-Crafty

目录 信息收集 rustscan whatweb WEB 漏洞利用 漏洞说明 漏洞验证 提权 get user.txt get Administrator 总结 信息收集 rustscan ┌──(root㉿ru)-[~/kali/hackthebox] └─# rustscan -a 10.10.11.249 --range0-65535 --ulimit5000 -- -A -sC [~] Automatically…

NLP:自定义模型训练

书接上文&#xff0c;为了完成指定的任务&#xff0c;我们需要额外训练一个特定场景的模型 这里主要参考了这篇博客&#xff1a;大佬的博客 我这里就主要讲一下我根据这位大佬的博客一步一步写下时&#xff0c;遇到的问题&#xff1a; 文中的cfg在哪里下载&#xff1f; 要不…

Fastjson漏洞利用合集

0x01 Fastjson 概述 1.应用场景 接口返回数据 Ajax异步访问数据RPC远程调用前后端分离后端返回的数据开放API(一些公司开放接口的时候&#xff0c;我们点击请求&#xff0c;返回的数据是JSON格式的)企业间合作接口(数据对接的时候定义的一种规范&#xff0c;确定入参&#x…

BUUCTF-MISC-[HDCTF2019]信号分析1

题目链接&#xff1a;BUUCTF在线评测 (buuoj.cn) 下载附件是一个WAV的文件&#xff0c;题目又叫做信号分析&#xff0c;用Adobe Audition 打开分析了 发现有很多长短不一样的信号&#xff0c;只需要分析一段 猜测长的是一短的为0 最后得到0101010101010101000000110 百度得知…

vscode如何远程到linux python venv虚拟环境开发?(python虚拟环境、vscode远程开发、vscode远程连接)

文章目录 1. 安装VSCode2. 安装扩展插件3. 配置SSH连接4. 输入用户名和密码5. 打开远程文件夹6. 创建/选择Python虚拟环境7. 安装Python插件 Visual Studio Code (VSCode) 提供了一种称为 Remote Development 的功能&#xff0c;允许用户在远程系统、容器或甚至 Windows 子系统…

【致逝去的青春】《龙珠》作者鸟山明逝世,享年68岁

鸟山明工作室&#xff08;BIRD STUDIO&#xff09;于3月8日发布讣告&#xff1a;鸟山明已于2024年3月1日因急性硬膜下血肿逝世&#xff0c;享年68岁。 《龙珠》从 1984 年开始于《周刊少年Jump》连载&#xff0c;过后曾改编曾多部动画、剧场版、游戏&#xff0c;相关周边商品也…

opengl 学习(二)-----你好,三角形

你好&#xff0c;三角形 分类demo效果解析 分类 opengl c demo #include "glad/glad.h" #include "glfw3.h" #include <iostream> #include <cmath> #include <vector>using namespace std;/** * 在学习此节之前&#xff0c;建议将这…

Alveo 概念拓扑结构

在 Alveo 加速卡中,涉及到的概念拓扑结构主要包括 Alveo 卡上的各个关键组件以及与主机系统之间的通信结构。以下是对这些概念拓扑结构的简要介绍: 1.DDR 即双数据率内存(Double Data Rate memory),是一种常见的计算机内存类型,用于存储和提供处理器所需的数据和指令。…

macos m1 arm芯片 使用jpype报错 FileNotFoundError: [Errno 2] JVM DLL not found

startJVM(jpype.getDefaultJVMPath()) 报错 Traceback (most recent call last):File "/Users/thomas990p/PycharmProjects/tuya/volcano-biz-scripts/WenKongFa/FinalCode/java2python/CallJavaAPI.py", line 12, in <module>startJVM(jpype.getDefaultJVMPa…

基于springboot实现大学生兼职网站系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现大学生兼职系统演示 摘要 现代化的市场中&#xff0c;人们日常的工作、生活都在不断的提速&#xff0c;而人们在工作与生活中与互联网的结合也越来越紧密&#xff0c;通过与互联网紧密的结合可以更好地实现日常工作的线上化、信息化、便捷化。现如今的各行各…

ebpf入门---监听所有新进程

什么是ebpf eBPF 全称 extended Berkeley Packet Filter&#xff0c;中文意思是 扩展的伯克利包过滤器。一般来说&#xff0c;要向内核添加新功能&#xff0c;需要修改内核源代码或者编写 内核模块 来实现。而 eBPF 允许程序在不修改内核源代码&#xff0c;或添加额外的内核模…