双向链表的实现

带头+双向+循环链表

  • 1. 项目头文件
  • 2. 具体实现功能
    • 2.1 双向链表的初始化
    • 2.2 双向链表尾插
    • 2.3 双向链表头插
    • 2.4 双向链表尾删
    • 2.5 双向链表头删
    • 2.6 双向链表查找
    • 2.7 双向链表在pos的前面进行插入
    • 2.8 双向链表删除pos位置的节点
    • 2.9 双向链表打印
    • 2.10 双向链表销毁

我们上篇博客进行了单链表的实现,这次就实现一下双链表:

1. 项目头文件

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{LTDataType _data;struct ListNode* _next;struct ListNode* _prev;
}ListNode;// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

2. 具体实现功能

2.1 双向链表的初始化

ListNode* ListCreate()
{ListNode* phead = (ListNode*)malloc(sizeof(ListNode));if (phead == NULL){perror("malloc");return NULL;}phead->_data = -1;phead->_next = phead;phead->_prev = phead;return phead;
}

创建一个哨兵位头结点,前后都指向自己,再返回链表的头结点。

2.2 双向链表尾插

ListNode* BuyNode(LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){perror("malloc");return NULL;}newnode->_next = NULL;newnode->_prev = NULL;newnode->_data = x;return newnode;
}// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyNode(x);ListNode* tail = pHead->_prev;newnode->_prev = tail;tail->_next = newnode;newnode->_next = pHead;pHead->_prev = newnode;
}

和单链表一样,添加操作时都需要创建一个新的结点,但与单链表不同的是,此时不必再判断是否为空(因为有了哨兵位头结点),并且尾插时找尾结点也不用依次遍历,直接找头结点的前驱。

2.3 双向链表头插

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyNode(x);ListNode* first = pHead->_next;pHead->_next = newnode;newnode->_prev = pHead;newnode->_next = first;first->_prev = newnode;
}

此时,也不用判断是否为空了(因为有了哨兵位头结点)。

2.4 双向链表尾删

bool LTEmpty(ListNode* pHead)
{return pHead->_next == pHead;
}// 双向链表尾删
void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!LTEmpty(pHead));ListNode* tail = pHead->_prev;ListNode* tailPrev = tail->_prev;pHead->_prev = tailPrev;tailPrev->_next = pHead;free(tail);
}

尾删时,直接断言哨兵位不能为空。

2.5 双向链表头删

// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!LTEmpty(pHead));ListNode* first = pHead->_next;ListNode* second = first->_next;free(first);pHead->_next = second;second->_prev = pHead;}

头删也一样,直接断言哨兵位不能为空。

2.6 双向链表查找

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;
}

需要注意的是,开始是从哨兵位头结点后一个结点开始遍历的,结束的条件是当其和哨兵位头结点相同时,则循环结束。所以这整个链表的设计是非常之巧妙的,带有工学之美的。

2.7 双向链表在pos的前面进行插入

void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* prev = pos->_prev;ListNode* newnode = BuyNode(x);prev->_next = newnode;newnode->_prev = prev;newnode->_next = pos;pos->_prev = newnode;}

在进行插入时,需要与查找函数相互配合。我们把查找到的结点返回给插入函数的pos。

2.8 双向链表删除pos位置的节点

// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{assert(pos);ListNode* posPrev = pos->_prev;ListNode* posNext = pos->_next;posPrev->_next = posNext;posNext->_prev = posPrev;free(pos);}

删除也是一样的,跟查找函数进行配合。

2.9 双向链表打印

void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->_next;printf("哨兵位<=>");while (cur != pHead){printf("%d<=>",cur->_data);cur = cur->_next;}printf("\n");
}

2.10 双向链表销毁

// 双向链表销毁
void ListDestory(ListNode* pHead)
{ListNode* cur = pHead->_next;while (cur != pHead){ListNode* next = cur->_next;free(cur);cur = next;}free(pHead);
}

打印和销毁也非常简单,就不细说了。总体而言,带头+双向+循环链表的实现比单链表简单多了。

代码参考: https://gitee.com/yujin518/test_c/tree/master/test_3_17

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

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

相关文章

27-2 文件上传漏洞 - 前端绕过

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 前端绕过思路 - 禁用 JavaScript: 背景: 当前开发行业大多采用前后端分离模式,后端使用多种开发语言如 PHP、Java 等,而前端主要使用 JavaScript(JS)。因此,禁用 JavaScrip…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的火焰与烟雾检测系统详解(深度学习模型+UI界面升级版+训练数据集)

摘要&#xff1a;本研究详细介绍了一种集成了最新YOLOv8算法的火焰与烟雾检测系统&#xff0c;并与YOLOv7、YOLOv6、YOLOv5等早期算法进行性能评估对比。该系统能够在包括图像、视频文件、实时视频流及批量文件中准确识别火焰与烟雾。文章深入探讨了YOLOv8算法的原理&#xff0…

Django实现登录注册

Django实现登录注册 目录 Django实现登录注册配置路由首页注册前端&#xff1a;后端&#xff1a; 登录前端&#xff1a;后端&#xff1a;验证码部分逻辑 配置路由 首先分发路由[User,Blog,Article] from django.contrib import admin from django.urls import path from Blog…

深度学习——yolov5的txt和xml互转

在学习工作的过程中&#xff0c;有时会需要自己新建数据集&#xff0c;向训练数据中添加新的数据&#xff0c;存在已有模型对新数据进行检测&#xff0c;得到yolov5对应的txt文件&#xff0c;之后转成xml&#xff0c;使用标注工具对数据进行校正。后续将xml转成yolov5训练使用的…

误删电脑C盘要重装系统吗 误删电脑C盘文件怎么恢复 误删c盘系统文件怎么修复 不小心删除C盘的东西恢复

C盘通常是操作系统(如Windows)的默认安装目录。它包含了操作系统的核心文件、驱动程序及系统所需的各种支持文件。这些文件对于计算机的正常运行至关重要。如果我们不小心将C盘的重要文件删除&#xff0c;会导致应用无法打开。本篇文章&#xff0c;我们将学习误删电脑C盘要重装…

面试算法-39-删除链表的倒数第 N 个结点

题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5] 解 class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {L…

基于支持向量机SVM的沉降预测,SVM详细原理,Libsvm详解

目录 支持向量机SVM的详细原理 SVM的定义 SVM理论 Libsvm工具箱详解 简介 参数说明 易错及常见问题 完整代码和数据下载链接:基于支持向量机SVM的沉降预测资源-CSDN文库 https://download.csdn.net/download/abc991835105/88947544 SVM应用实例,基于支持向量机SVM的沉降预测…

vim,gcc,gdb与Makefile的使用

一、Linux编辑器-vim使用 1.vim的基本概念 vim的三种模式(其实有好多模式&#xff0c;目前掌握这3种即可),分别是命令模式&#xff08;command mode&#xff09;、插入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08;last line mode&#xff09;&#xff0c;…

指挥航空公司架次与延误率占比

打开前端Vue项目kongguan_web&#xff0c;创建前端 src/components/Delay.vue 页面&#xff0c;并添加柱状图与折线图叠加&#xff0c;设置双Y轴。 页面div设计&#xff0c;代码如下&#xff1a; <template><div><div class"home"><div id&qu…

AJAX-XMLHttpRequest

XMLHttpRequest 定义&#xff1a; XMLHttpRequest对象用于与服务器交互。通过XMLHttpRequest可以在不断刷新页面的情况下请求特定URL&#xff0c;获取数据。这允许网页在不影响用户操作的情况下&#xff0c;更新页面的局部内容。 关系&#xff1a; axios内部采用XMLHttpReques…

关于volatile与指令重排序的探讨

写在开头 在之前的学习我们了解到&#xff0c;为了充分利用缓存&#xff0c;提高程序的执行速度&#xff0c;编译器在底层执行的时候&#xff0c;会进行指令重排序的优化操作&#xff0c;但这种优化&#xff0c;在有些时候会带来 有序性 的问题。 那何为有序性呢&#xff1f;…

乘积尾零啊填空题)

乘积尾零 题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 如下的 10 行数据&#xff0c;每行有 10 个整数&#xff0c;请你求出它们的乘积的末尾有多少个零? 的乘积的末尾有多少个零? 5650 4542 3554 473 946 4…

Halcon OCR文字识别

1、OCR文字识别 OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;工具对图像中的文字进行识别和分析。 FontFile : Universal_0-9_NoRej dev_update_window (off) read_image (bottle, bottle2) get_image_size (bottle, Width, Height) dev…

JavaScript 中实现请求并发控制

文章目录 浏览器并发请求限制数&#xff08;图&#xff09;实现代码三方插件 假设有 30 个待办任务要执行&#xff0c;而我们希望限制同时执行的任务个数&#xff0c;即最多只有 3 个任务能同时执行。当正在执行任务列表 中的任何 1 个任务完成后&#xff0c;程序会自动从 待办…

(赋值)运算符号重载

概念以及语法 运算符重载&#xff1a;operator 函数原型&#xff1a;返回值类型 operator 操作符&#xff08;参数列表&#xff09; //操作符有几个操作数就有几个参数 //操作符只包含C/C已经有的&#xff0c;就是说我们不能创建新的操作符&#xff0c;只能重载已有的运算符 …

VMware安装Ubuntu 18.04.2

下载Ubuntu映像 下载地址&#xff1a;http://old-releases.ubuntu.com/releases/18.04/ 下载名称&#xff1a; ubuntu-18.04.2-desktop-amd64.iso 清华镜像站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 阿里云镜像站&#xff1a;https://mirrors.ali…

python 统计中国观鸟记录中心官网已观测的鸟类种类

python 统计中国观鸟记录中心官网已观测的鸟类种类 中国观鸟记录中心网站&#xff1a;https://www.birdreport.cn/ 先下载官网 Excel 文件 文件放置目录如下&#xff1a; home dataset xxx.xlsxxxx.xlsxxxx.xlsx Excelgrep.py &#xff08;进行文件内容提取的程序&#xff…

关于Ubuntu虚拟机突然上不了网的问题

今天刚重新把Ubuntu虚拟机下回来准备大干一场&#xff0c;结果去吃饭回来虚拟机就上不去网了&#xff0c;具体体现为右上角没有网络的图标&#xff0c;下图是有网络的情况&#xff0c;废话不多说&#xff0c;直接给出解决方案&#xff1a;博客在此 我就是运行了这三行代码就成功…

如何杀死服务器出现的僵尸进程

今天在服务器上进行深度学习训练的时候&#xff0c;发现已经结束程序代码&#xff0c;但是GPU还是显示显存在运行。 为了解决这些问题&#xff0c;网上查找了大量的资料&#xff0c;发现是因为僵尸进程的原因&#xff0c;因此记录相关的解决步骤&#xff0c;方便自己和大家。 …

Error: Unable to find git in your PATH. flutter dart

我的是重装git &#xff0c;参考 flutter Unable to find git in your PATH - ZJH_BLOGS - 博客园 (cnblogs.com)