数据结构初阶之双向链表的介绍与双向链表的实现

news2025/1/24 13:46:51

一、概念与结构

带头双向循环链表

next :指向下一个结点(后继结点)

prev :指向前一个结点(前驱结点)

二、实现双向链表

项目创建的时候,要创建一个头文件(.h)List.h ,两个源文件(.c)List.ctest.c 。List.h 用于定义结构体和声明函数;List.c 用于实现函数;test.c 用于测试函数,每实现一个函数要进行相应的测试。编写代码过程中要勤测试,避免写出大量代码后再测试,如果出现问题,问题无从定位。

1、List.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

//定义双向链表的结构
typedef int DataType;
typedef struct ListNode
{
    DataType data; 
    struct ListNode* next;
    struct ListNode* prev;
}ListNode;

//申请一个新节点
ListNode* buy_Node(DataType x);

//双向链表的初始化,申请一个头结点
ListNode* init_List(void);

//打印双向链表
void print_List(ListNode* head);

//尾插一个结点
void pushback_Node(ListNode* head, DataType x);

//头插一个结点
void pushfront_Node(ListNode* head, DataType x);

//判断链表是否为空链表
bool empty_List(ListNode* head);

//尾删一个结点
void popback_Node(ListNode* head);

//头删一个结点
void popfront_Node(ListNode* head);

//查找指定结点
ListNode* find_Node(ListNode* head, DataType x);

//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x);

//删除指定 pos 位置的结点
void erase_Node(ListNode* pos);

//销毁双向链表
void destory_List(ListNode* head);

2、List.c


#include"List.h"

//申请一个新节点
ListNode* buy_Node(DataType x)
{
    ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
    if (!newnode)
    {
        perror("malloc fail!");
        exit(1);
    }
    newnode->data = x;
    newnode->next = newnode->prev = newnode;
    return newnode;
}

//双向链表的初始化,申请一个头结点
ListNode* init_List(void)
{
    ListNode* plist = buy_Node(-1);
    return plist;
}

//打印双向链表
void print_List(ListNode* head)
{
    ListNode* pcur = head->next;
    while (pcur != head)
    {
        printf("%d -> ", pcur->data);
        pcur = pcur->next;
    }
    printf("\n");
}

//判断链表是否为空链表
bool empty_List(ListNode* head)
{
    assert(head);
    return head->next != head;
}


//尾插一个结点
void pushback_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* newnode = buy_Node(x);
    newnode->next = head;
    newnode->prev = head->prev;
    head->prev->next = newnode;
    head->prev = newnode;
}

//头插一个结点
void pushfront_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* newnode = buy_Node(x);
    newnode->next = head->next;
    newnode->prev = head;
    head->next->prev = newnode;
    head->next = newnode;
}

//尾删一个结点
void popback_Node(ListNode* head)
{
    assert(empty_List(head));
    ListNode* del = head->prev;
    head->prev = del->prev;
    del->prev->next = head;
    free(del);
    del = NULL;
}
//头删一个结点
void popfront_Node(ListNode* head)
{
    assert(empty_List(head));
    ListNode* del = head->next;
    del->next->prev = head;
    head->next = del->next;
    free(del);
    del = NULL;
}

//查找指定结点
ListNode* find_Node(ListNode* head, DataType x)
{
    assert(head);
    ListNode* pcur = head->next;
    while (pcur != head)
    {
        if (pcur->data == x)
            return pcur;
        pcur = pcur->next;
    }
    return NULL;
}

//在 pos 位置之后插入一个结点
void insert_Node(ListNode* pos, DataType x)
{
    assert(pos);
    ListNode* newnode = buy_Node(x);
    newnode->next = pos->next;
    newnode->prev = pos;
    pos->next->prev = newnode;
    pos->next = newnode;
}

//删除指定 pos 位置的结点
void erase_Node(ListNode* pos)
{
    assert(pos);
    pos->next->prev = pos->prev;
    pos->prev->next = pos->next;
    free(pos);
    pos = NULL;
}

//销毁双向链表
void destory_List(ListNode** head)
{
    ListNode* pcur = (*head)->next;
    while (pcur != *head)
    {
        ListNode* next = pcur->next;
        free(pcur);
        pcur = next;
    }
    free(*head);
    *head = NULL;
}

test.c自行测试,这里不予提供。

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

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

相关文章

CICD集合(六):Jenkins配置Editable Email Notification

CICD集合(六):Jenkins配置Editable Email Notification 1、系统配置 1.1、Jenkins Location 1.2、邮件通知 1、SMTP服务器:imap.exmail.qq.com (因qq企业邮箱) 2、邮箱后缀:@xxx.com 3、勾选:使用SMTP认证 用户名:

Golang 中除了加锁还有哪些安全读写共享变量的方式?

Golang 中除了加锁还有哪些安全读写共享变量的方式&#xff1f; 在 Golang 中&#xff0c;除了使用 Mutex 锁来保护共享变量外&#xff0c;还可以通过 Channel 和 原子性操作 来实现安全读写共享变量。 1. 使用 Channel 原理 Channel 是 Golang 中用于 Goroutine 之间通信的…

应用层协议 HTTP 讲解实战:从0实现HTTP 服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; HTTP 协议 &#x1f98b; 认识 URL&#x1f98b; urlencode 和 urldecode 二&#xff1a;&#x1f525; HTTP 协议请求与响应格式 &#x1f98b; HTTP 请求…

F/V/F/I频率脉冲信号转换器

F/V/F/I频率脉冲信号转换器 概述&#xff1a;捷晟达科技的JSD TFA-1001系列是一进一出频率脉冲信号转换器(F/V转换器),该频率转换器是将频率脉冲信号(方波、正弦波、锯齿波)转换成国际标准的模拟量电压(电流)信号,并远距离无失真传送到控制室(如:PLC,DCS,AD,PC采集系统)产品的输…

Windows的docker中安装gitlab

一.Windows的docker中安装gitlab 1.通过阿里云拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/lab99/gitlab-ce-zh 2.在本地创建备份数据的目录 mkdir -p D:home/software/gitlab/etc mkdir -p D:home/software/gitlab/logs mkdir -p D:home/software/gitlab/dat…

【Linux】理解Linux中一切皆文件、缓冲区、ext2文件系统、软硬链接

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、如何理解在Linux中一切皆文件&#xff1f;1.1 概述1.2 文件类型1.3 优势 2、缓冲区2.1 为什么要引入缓冲区&#xff1f;2.2 缓…

在Docker 容器中安装 Oracle 19c

在 Docker 容器中安装 Oracle 19c 是可行的&#xff0c;但它相较于其他数据库&#xff08;如 MySQL、PostgreSQL 等&#xff09;会复杂一些&#xff0c;因为 Oracle 数据库有一些特定的要求&#xff0c;如操作系统和库的依赖&#xff0c;以及许可证问题。 不过&#xff0c;Ora…

【数据库】详解MySQL数据库中的事务与锁

目录 1.数据库事务 1.1.事务的四大特性 1.2.事务开启的方式 1.3.读一致性问题及其解决 2.MVCC解决读一致性问题原理 2.1.MVCC概念 2.2.准备环境 3.MySQL中的锁 3.1.行锁之共享锁 3.2.行锁之排它锁 1.数据库事务 数据库事务&#xff08;Transaction&#xff09;是一种…

springboot 配置redis

环境配置 springboot3.4 redis5.0.14 redis准备参考下面文章 window下安装redis以及启动 redis客户端安装 引入依赖 <!-- 集成redis依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-…

EEG代码实践:diffusion EEG——扩散模型生成EEG信号

2024/1/22&#xff1a; 原始EEG信号的生成说实话一直做不到让人满意的水平&#xff0c;之前做的MIEEG复现也迟迟没有调整到自己想要的程度&#xff0c;与论文中的效果还是有些差距。改换思路使用离散小波变换&#xff0c;用变换之后的信号做生成任务则好了许多。从大二开始一直…

Banana Pi BPI-RV2 开发板矽昌通信 RISC-V路由芯片SF21H8898优势亮点

Banana Pi BPI-RV3开源路由器 1. 8898芯片具备强大的网络加速硬件性能&#xff0c;能够在小字节报文条件下实现高效数据转发&#xff1a;  单WAN口性能&#xff1a;支持 64 字节报文单向转发速率达到 2.5 Gbps&#xff0c;双向转发速率为 5 Gbps。双WAN口性能&#xff1a;支…

光谱相机在智能冰箱的应用原理与优势

食品新鲜度检测 详细可点击查看汇能感知团队实验报告&#xff1a;高光谱成像技术检测食物新鲜度 检测原理&#xff1a;不同新鲜程度的食品&#xff0c;其化学成分和结构会有所不同&#xff0c;在光谱下的反射、吸收等特性也存在差异。例如新鲜肉类和蔬菜中的水分、蛋白质、叶…

xxljob执行失败,xxl-job remoting error(sl.nts.com), for url : http://xxxxxxxxxx/run

问题 项目部署后&#xff0c;发现xxljob没有正常工作&#xff0c;报错 尝试解决&#xff1a; &#xff08;1&#xff09;检查xxljob配置&#xff08;无问题&#xff09; &#xff08;2&#xff09;检查服务器hosts文件域名配置&#xff08;依旧无问题&#xff09; 各种能检查…

什么是全息展示

全息展示。这一术语来源于“全息图”&#xff08;Holography&#xff09;的概念&#xff0c;而“全息图”这个词是由希腊词根 "holos" 演变而来&#xff0c;意为“整体的”或“完整的”。全息技术的核心在于它能够捕捉并再现物体的所有光学信息——不仅仅是强度&…

服务器内部是如何运行的

服务器内部的运行可以从硬件和软件两个方面来解释。 一、硬件层面 服务器的硬件与普通计算机相似,但它通常具有更高的性能和更强的扩展性。服务器硬件包括: 1.中央处理单元(CPU):负责执行服务器上的计算任务。服务器一般配备多核心的高性能CPU,以支持多个请求并行处理…

【Linux】文件操作、系统IO相关操作、inode和输入输出重定向

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、理解文件1.1 狭义理解1.2 广义理解1.3 文件操作1.4 系统角度 2、系统文件IO2.1 文件相关操作2.2 文件描述符2.3 重定向 3、动静…

Jetson Xavier NX (ARM) 使用 PyTorch 安装 Open3D-ML 指南

由于 Jetson 为 ARM64 (aarch64) 的系统架构&#xff0c;所以不能用 pip install 直接安装&#xff0c;需要通过源码编译。 升级系统 JetPack 由于 Open3D-ML 目前只支持 CUDA 10.0 以及 CUDA 11.*&#xff0c;并且 JetPack 的 CUDA 开发环境只有10.2、11.4以及12.2&#xff0…

【Vim Masterclass 笔记25】S10L45:Vim 多窗口的常用操作方法及相关注意事项

文章目录 S10L45 Working with Multiple Windows1 水平分割窗口2 在水平分割的新窗口中显示其它文件内容3 垂直分割窗口4 窗口的关闭5 在同一窗口水平拆分出多个窗口6 关闭其余窗口7 让四个文件呈田字形排列8 光标在多窗口中的定位9 调节子窗口的尺寸大小10 变换子窗口的位置11…

《keras 3 内卷神经网络》

keras 3 内卷神经网络 作者&#xff1a;Aritra Roy Gosthipaty 创建日期&#xff1a;2021/07/25 最后修改时间&#xff1a;2021/07/25 描述&#xff1a;深入研究特定于位置和通道无关的“内卷”内核。 &#xff08;i&#xff09; 此示例使用 Keras 3 在 Colab 中查看 GitHub …

Linux 进程环境变量:深入理解与实践指南

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; &#x1f6a9;用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 在 Linux 系统里…