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

链表之双向链表的实现

铁汁们大家好,我们上一篇博客学习了单链表,这节课让我们继续往深学习,学习一下双线链表,话不多说,我们开始吧!



目录

1.双向链表

2.顺序表和链表的优缺点

3.双向链表的实现


1.双向链表

1.我们要实现的双线链表是带头双向循环链表,它的结构最复杂,一般用在单独的存储数据。我们实际中使用的链表数据结构都是带头双向循环链表。

2.它虽然结构复杂,但是在我们用代码实现过程中,它比单链表简单。

3.相信很多铁汁不清楚双向链表的结构是什么,如下图:

2.顺序表和链表的优缺点

我们在这里总结一下这两种线性表,方便之后的学习。

顺序表:

优点:空间连续,支持随机访问

缺点:中间或前面部分的插入和删除,时间复杂度是O(n);

           增容很不方便,代价较大。

链表:

优点:任意位置的插入删除,时间复杂度为O(1);

           没有增容销耗,按需申请节点空间,不用了直接释放。

缺点:以节点为单位存储,不支持随机访问

3.双向链表的实现

经过上面的铺垫,我们来实现一个带头双向循环链表

List.h文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int ADataType;
typedef struct ListNode
{ADataType data;struct ListNode* prev;//双线链表前驱指针struct ListNode* next;//后继指针
}LN;//双向链表初始化
LN* ListInit();
//为节点开辟空间
LN* BuyListCapacity(ADataType x);
//链表的销毁
void ListDestory(LN* phead);
//头插
void ListPushFront(LN* phead, ADataType x);
//尾插
void ListPushBack(LN* phead, ADataType x);
//打印
void ListPrint(LN* phead);
//头删
void ListPopFront(LN* phead);
//尾删
void ListPopBack(LN* phead);
//查找链表中的数据
LN* ListSearch(LN* phead, ADataType x);
//修改找到的数据
void ListModify( LN* pos, ADataType y);
//在这个位置后插入数据
void ListInsert(LN* pos, ADataType x);
//删除这个位置之后的数据
void ListErase(LN* pos);
//判断链表是否为空
bool ListEmpty(LN* phead);

List.c文件

#include"List.h"//为节点开辟空间
LN* BuyListCapacity(ADataType x)
{LN* newnode = (LN*)malloc(sizeof(LN));if (newnode == NULL){perror("malloc is false!\n");exit(-1);}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}//双向链表初始化
LN* ListInit()
{//开辟空间LN* phead = BuyListCapacity(0);//让头节点的前驱和后继都指向自己,是一个循环phead->next = phead;phead->prev = phead;return phead;
}//链表的销毁
void ListDestory(LN* phead)
{assert(phead);LN* tail = phead->next;while (tail != phead)//链表的头尾相连,当尾等于头时,说明链表空了{LN* next = tail->next;free(tail);tail = next;}free(phead);phead = NULL;
}
//头插
void ListPushFront(LN* phead, ADataType x)
{assert(phead);LN* newnode = BuyListCapacity(x);//若这里不使用新的变量来存储原来第一个节点的值,就先链接后,在链接前newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;newnode->prev = phead;
}
//尾插
void ListPushBack(LN* phead, ADataType x)
{assert(phead);LN* newnode = BuyListCapacity(x);//找到尾,进行插入节点LN* tail = phead->prev;tail->next = newnode;newnode->prev = tail;phead->prev = newnode;newnode->next = phead;
}
//打印
void ListPrint(LN* phead)
{assert(phead);LN* tail = phead->next;while (tail != phead){printf(" %d ", tail->data);tail = tail->next;}printf("\n");
}
//头删
void ListPopFront(LN* phead)
{assert(phead);//判断链表是否为空,为空则删不了if (phead->next == phead){printf("List is NULL!\n");return;}//先记录下后一个节点LN* first = phead->next;LN* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;
}
//尾删
void ListPopBack(LN* phead)
{assert(phead);//判断链表是否为空if (phead->prev == phead){printf("List is NULL!\n");return;}LN* tail = phead->prev;LN* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;
}
//查找链表中的数据
LN* ListSearch(LN* phead, ADataType x)
{assert(phead);LN* cur = phead->next;while (cur->data != x){cur = cur->next;}if (cur->data == x){return cur;}return NULL;
}
//修改找到的数据
void ListModify( LN* pos, ADataType y)
{assert(pos);pos->data = y;
}
//在这个位置后插入数据
void ListInsert(LN* pos, ADataType x)
{assert(pos);LN* newnode = BuyListCapacity(x);LN* next = pos->next;pos->next = newnode;newnode->prev = pos;newnode->next = next;next->prev = newnode;
}
//删除这个位置之后的数据
void ListErase(LN* pos)
{assert(pos);LN* cur = pos->next;LN* next = cur->next;pos->next = next;next->prev = pos;free(cur);cur = NULL;
}
//判断链表是否为空
bool ListEmpty(LN* phead)
{assert(phead);if (phead->prev == phead || phead->next == phead){return true;}return false;
}

Test.c文件

#include"List.h"
//带头双向循环链表的实现void Test1()
{LN* head = ListInit();ListPushFront(head, 33);ListPushFront(head, 22);ListPushFront(head, 11);ListPushBack(head, 4);ListPushBack(head, 5);ListPushBack(head, 6);ListPushBack(head, 7);ListPushBack(head, 8);ListPushBack(head, 9);ListPushBack(head, 10);printf("ListNode:> ");ListPrint(head);ListPopFront(head);ListPopBack(head);printf("ListNode:> ");ListPrint(head);LN* pos = ListSearch(head, 7);if (pos == NULL){printf("Not Find!\n");}else{printf("the number is %d\n", pos->data);ListModify(pos, 77);printf("ListNode:> ");ListPrint(head);ListInsert(pos, 13);ListInsert(pos, 14);ListInsert(pos, 15);printf("ListNode:> ");ListPrint(head);ListErase(pos);printf("ListNode:> ");ListPrint(head);}if (ListEmpty(head)){printf("List is NULL!\n");}else{printf("List is Notnull!\n");}ListDestory(head);printf("List is disory!\n");
}int main()
{Test1();return 0;
}

结果:结果就是这样的,大家可以自己尝试一下!


这就是双向链表的实现,大家还是要自己敲一遍代码,帮助自己更好的掌握知识点。

谢谢铁汁们的支持,咱们下期再见!!!

相关文章:

链表之双向链表的实现

铁汁们大家好&#xff0c;我们上一篇博客学习了单链表&#xff0c;这节课让我们继续往深学习&#xff0c;学习一下双线链表&#xff0c;话不多说&#xff0c;我们开始吧&#xff01; 目录 1.双向链表 2.顺序表和链表的优缺点 3.双向链表的实现 1.双向链表 1.我们要实现的双线…...

小白学大模型:什么是生成式人工智能?

什么是生成式人工智能&#xff1f; 在过去几年中&#xff0c;机器学习领域取得了迅猛进步&#xff0c;创造了人工智能的一个新的子领域&#xff1a;生成式人工智能。这些程序通过分析大量的数字化材料产生新颖的文本、图像、音乐和软件&#xff0c;我将这些程序简称为“GAIs”…...

并发编程01-深入理解Java并发/线程等待/通知机制

为什么我们要学习并发编程&#xff1f; 最直白的原因&#xff0c;因为面试需要&#xff0c;我们来看看美团和阿里对 Java 岗位的 JD&#xff1a; 从上面两大互联网公司的招聘需求可以看到&#xff0c; 大厂的 Java 岗的并发编程能力属于标配。 而在非大厂的公司&#xff0c; 并…...

3.类与对象(中篇)介绍了类的6个默认构造函数,列举了相关案例,实现了一个日期类

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会…...

Vue实现手机APP页面的切换,如何使用Vue Router进行路由管理呢?

在Vue中&#xff0c;实现手机APP页面的切换&#xff0c;通常会使用Vue Router进行路由管理。Vue Router是Vue.js官方的路由管理器&#xff0c;它和Vue.js深度集成&#xff0c;使构建单页面应用变得易如反掌。 以下是一个简单的步骤说明&#xff0c;展示如何使用Vue Router实现…...

软考--软件设计师(软件工程总结2)

目录 1.测试方法 2.软件项目管理 3.软件容错技术 4.软件复杂性度量 5.结构化分析方法&#xff08;一种面向数据流的开发方法&#xff09; 6.数据流图 1.测试方法 软件测试&#xff1a;静态测试&#xff08;被测程序采用人工检测&#xff0c;计算机辅助静态分析的手段&…...

渗透测试之SSRF漏洞

一、SSRF介绍 SSRF&#xff08;Cross-site Scripting&#xff0c;简称XSS&#xff09;是一种安全漏洞&#xff0c;它允许攻击者通过构造特定的请求&#xff0c;使服务器发起对外网无法访问的内部系统请求。这种漏洞通常发生在服务端提供了从其他服务器应用获取数据的功能&#…...

【C++】1957. 求三个数的平均数

问题&#xff1a;1957. 求三个数的平均数 类型&#xff1a;基本运算、小数运算 题目描述&#xff1a; 小雅刚刚考完语文、数学、英语的三门期中考试&#xff0c;她想请你编个程序来帮她算算她的平均分。 要求输入三个正整数&#xff0c;分别表示三科考试的分数&#xff0c;输…...

GPU部署ChatGLM3

首先&#xff0c;检查一下自己的电脑有没有CUDA环境&#xff0c;没有的话&#xff0c;去安装一个。我的电脑是4060显卡&#xff0c;买回来就自带这些环境了。没有显卡的话&#xff0c;也不要紧&#xff0c;这个懒人安装包支持CPU运行&#xff0c;会自动识别没有GPU&#xff0c;…...

Windows远程执行

Windows远程执行 前言 1、在办公环境中&#xff0c;利用系统本身的远程服务进行远程代码执行甚至内网穿透横向移动的安全事件是非常可怕的&#xff0c;因此系统本身的一些远程服务在没有必要的情况下建议关闭&#xff0c;防止意外发生&#xff1b; 2、作为安全人员&#xff0…...

AJAX —— 学习(一)

目录 一、原生 AJAX &#xff08;一&#xff09;AJAX 介绍 1.理解 2.作用 3.最大的优势 4.应用例子 &#xff08;二&#xff09;XML 介绍 1.理解 2.作用 &#xff08;三&#xff09;AJAX 的特点 1.优点 2.缺点 二、HTTP 协议 &#xff08;一&#xff09;HTTP 介…...

Activity——idea(2020以后)配置actiBPM

文章目录 前言jar下载idea 安装本地扩展插件 前言 2020及之后版本的idea中&#xff0c;未维护对应的actiBPM扩展插件。如果需要安装该插件&#xff0c;则需要使用本地导入 jar的方式。 jar下载 访问官方网站&#xff0c;搜索对应的actiBPM扩展插件。 https://plugins.jetbra…...

MyBatis——配置优化和分页插件

MyBatis配置优化 MyBatis配置文件的元素结构如下&#xff1a; configuration&#xff08;配置&#xff09; properties&#xff08;属性&#xff09; settings&#xff08;设置&#xff09; typeAliases&#xff08;类型别名&#xff09; plugins&#xff08;插件&#xff09…...

[蓝桥杯 2013 省 B] 翻硬币

[蓝桥杯 2013 省 B] 翻硬币 题目背景 小明正在玩一个“翻硬币”的游戏。 题目描述 桌上放着排成一排的若干硬币。我们用 * 表示正面&#xff0c;用 o 表示反面&#xff08;是小写字母&#xff0c;不是零&#xff09;&#xff0c;比如可能情形是 **oo***oooo&#xff0c;如果…...

[BT]BUUCTF刷题第13天(4.1)

第13天 Upload-Labs-Linux (Basic) Pass-01 根据题目提示&#xff0c;该题为绕过js验证。 一句话木马&#xff1a; <?php eval(system($_POST["cmd"]));?> // 符号 表示后面的语句即使执行错误&#xff0c;也不报错。 // eval() 把括号内的字符串全部…...

特别详细的Spring Cloud 系列教程1:服务注册中心Eureka的启动

Eureka已经被Spring Cloud继承在其子项目spring-cloud-netflix中&#xff0c;搭建Eureka Server的方式还是非常简单的。只需要通过一个独立的maven工程即可搭建Eureka Server。 我们引入spring cloud的依赖和eureka的依赖。 <dependencyManagement><!-- spring clo…...

Day108:代码审计-PHP模型开发篇MVC层动态调试未授权脆弱鉴权未引用错误逻辑

目录 案例1-Xhcms-动态调试-脆弱的鉴权逻辑 案例2-Cwcms-动态调试-未引用鉴权逻辑 案例3-Bosscms-动态调试-不严谨的鉴权逻辑 知识点&#xff1a; 1、PHP审计-动态调试-未授权安全 2、PHP审计-文件对比-未授权安全 3、PHP审计-未授权访问-三种形态 动态调试优点: 环境配置&…...

重读Java设计模式: 桥接模式详解

引言 在软件开发中&#xff0c;经常会遇到需要在抽象与实现之间建立连接的情况。当系统需要支持多个维度的变化时&#xff0c;使用传统的继承方式往往会导致类爆炸和耦合度增加的问题。为了解决这一问题&#xff0c;我们可以使用桥接模式。桥接模式是一种结构型设计模式&#…...

新规解读 | 被网信办豁免数据出境申报义务的企业,还需要做什么?

为了促进数据依法有序自由流动&#xff0c;激发数据要素价值&#xff0c;扩大高水平对外开放&#xff0c;《促进和规范数据跨境流动规定》&#xff08;以下简称《规定》&#xff09;对数据出境安全评估、个人信息出境标准合同、个人信息保护认证等数据出境制度作出优化调整。 …...

fakebook-攻防世界

题目 先目录扫描一下 dirseach 打开flag.php是空白的 访问robots.txt,访问user.php.bak <?php class UserInfo { public $name ""; public $age 0; public $blog ""; public function __construct($name, $age, $blog) { …...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...