【数据结构】双链表的定义和操作

news2024/11/15 18:16:09

目录

1.双链表的定义

2.双链表的创建和初始化

3.双链表的插入节点操作

4.双链表的删除节点操作

5.双链表的查找节点操作

6.双链表的更新节点操作

7.完整代码


🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。

💡本文由Filotimo__✍️原创,首发于CSDN📚。

📣如需转载,请事先与我联系以获得授权⚠️。

🎁欢迎大家给我点赞👍、收藏⭐️,并在留言区📝与我互动,这些都是我前进的动力!

🌟我的格言:森林草木都有自己认为对的角度🌟。

1.双链表的定义

双链表是一种常见的数据结构,它由一系列节点组成,每个节点包含两个指针,一个指向前一个节点,另一个指向后一个节点。与单链表不同的是,双链表的节点可以双向访问,因此可以在任意位置快速插入、删除和查找元素。

一个双链表通常包含以下属性和操作:
头节点(head):指向第一个节点的指针。
尾节点(tail):指向最后一个节点的指针。
节点(node):包含数据和两个指针的数据单元。
插入(insert):在指定位置插入一个新的节点。
删除(delete):删除指定位置的节点。
查找(search):根据给定的值查找节点。
遍历(traverse):按顺序访问链表中的每个节点。

2.双链表的创建和初始化

创建一个双链表需要定义一个结构体,包含数据域和前后指针域。初始化时要注意将头结点的前后指针均指向 NULL。

struct DNode {
    int data;  //数据域
    struct DNode *prior;  //前驱指针域
    struct DNode *next;   //后继指针域
};

struct DNode *createList() {
    struct DNode *head = (struct DNode*)malloc(sizeof(struct DNode));
    head->prior = NULL;
    head->next = NULL;
    return head;
}

定义结构体struct DNode表示双向链表的节点。
该节点包括三个成员变量:
int data表示节点的数据域,可以存储整数类型的数据。
struct DNode *prior表示指向前一个节点的指针域。
struct DNode *next表示指向后一个节点的指针域。

在createList函数内部,首先通过malloc函数动态分配了一块内存,大小为一个struct DNode结构体的大小。然后将分配的内存强制转换为struct DNode*类型,并将其赋值给head指针变量,作为链表的头节点。

3.双链表的插入节点操作

在插入节点时,需要将新节点插入到某个节点之前或之后,通过修改前后指针实现。具体操作分为两步,先将新节点的前后指针赋值,然后修改它前后节点的指针。需要注意判断特殊情况,如插入到空链表、插入到头结点等。

void insertNode(struct DNode *p, int data) {
    if (p == NULL) return;
    struct DNode *newNode = (struct DNode*)malloc(sizeof(struct DNode));
    newNode->data = data;
    newNode->prior = p;
    newNode->next = p->next;
    if (p->next != NULL) p->next->prior = newNode;
    p->next = newNode;
}

函数insertNode接受两个参数:指向双向链表结点的指针p和要插入的数据data。

如果p不为空,则创建一个新的双向链表结点newNode,通过malloc函数动态分配内存。然后,将新节点的data字段设置为传入的data值。再将新节点的prior字段设置为指向p,将新节点的next字段设置为指向p->next。

检查p的下一个结点是否为空,如果不为空,则将下一个结点的prior字段指向新节点newNode。最后将p的next指针指向新结点newNode,完成插入操作。这样,插入操作就将新节点插入到了链表中p结点之后的位置。

4.双链表的删除节点操作

在删除节点时,需先找到要删除的节点,然后修改前后节点的指针。在执行 free 操作后,需要将指针置为 NULL,避免出现野指针。

void deleteNode(struct DNode *p) {
    if (p == NULL) return;
    p->prior->next = p->next;
    if (p->next != NULL) p->next->prior = p->prior;
    free(p);
    p = NULL;
}

如果p不为空,将p结点的前驱结点的next指针指向p结点的后继结点,断开p结点与前后结点的连接。即p->prior->next = p->next。

检查p结点的后继结点是否为空,如果不为空,则将后继结点的前驱指针指向p结点的前驱结点,断开p结点与后继结点的连接。即p->next->prior = p->prior。

使用free函数释放了指针p指向的内存,将p结点从链表中删除。

将指针p设置为NULL,确保不再引用已经删除的结点。

5.双链表的查找节点操作

查找节点时,可以采用遍历的方法进行查找。需要注意判断特殊情况,如链表为空等。

struct DNode *findNode(struct DNode *head, int data) {
    if (head == NULL) return NULL;
    struct DNode *p = head->next;
    while (p != NULL) {
        if (p->data == data) return p;
        p = p->next;
    }
    return NULL;
}

如果head不为空,代码将p指针初始化为head结点的下一个结点,即head->next。

使用while循环遍历链表,如果指针p指向的结点的data字段等于要查找的数据data,则直接返回该结点的指针p,表示查找成功。

如果没有查找到要找的数据,即p到达链表结尾指针为NULL,则返回NULL,表示查找失败。

6.双链表的更新节点操作

更新节点操作与单链表类似,具体步骤为先查找要更新的节点,然后修改其数据域的值即可。

void updateNode(struct DNode *p, int newData) {
    if (p != NULL) {
        p->data = newData;
    }
}

首先检查指针p是否为空,如果不为空,则将指针p所指向的结点的data字段更新为新的数据newData。如果结点p为空,则不进行任何操作。

7.完整代码

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

//双链表结构体定义
struct DNode {
    int data;  //数据域
    struct DNode *prior;  //前驱指针域
    struct DNode *next;   //后继指针域
};

//创建双链表
struct DNode *createList() {
    struct DNode *head = (struct DNode*)malloc(sizeof(struct DNode));
    head->prior = NULL;
    head->next = NULL;
    return head;
}

//插入节点
void insertNode(struct DNode *p, int data) {
    if (p == NULL) return;
    struct DNode *newNode = (struct DNode*)malloc(sizeof(struct DNode));
    newNode->data = data;
    newNode->prior = p;
    newNode->next = p->next;
    if (p->next != NULL) p->next->prior = newNode;
    p->next = newNode;
}

//删除节点
void deleteNode(struct DNode *p) {
    if (p == NULL) return;
    p->prior->next = p->next;
    if (p->next != NULL) p->next->prior = p->prior;
    free(p);
    p = NULL;
}

//查找节点
struct DNode *findNode(struct DNode *head, int data) {
    if (head == NULL) return NULL;
    struct DNode *p = head->next;
    while (p != NULL) {
        if (p->data == data) return p;
        p = p->next;
    }
    return NULL;
}

//更新节点
void updateNode(struct DNode *p, int newData) {
    if (p != NULL) {
        p->data = newData;
    }
}

//遍历双链表
void traverseList(struct DNode *head) {
    if (head == NULL) return;
    struct DNode *p = head->next;
    while (p != NULL) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

//测试双链表
int main() {
    struct DNode *head = createList();  //创建链表

    //插入节点
    insertNode(head, 1);
    insertNode(head, 2);
    insertNode(head, 3);
    insertNode(head, 4);

    traverseList(head);  //遍历链表

    struct DNode *p = findNode(head, 2);  //查找节点
    if (p != NULL) {
        printf("Found node: %d\n", p->data);
        updateNode(p, 5);  //更新节点
        printf("After updated, the list is:\n");
        traverseList(head);  //遍历链表
    }

    deleteNode(findNode(head, 3)); //删除节点
    printf("After deleted, the list is:\n");
    traverseList(head);  //遍历链表

    return 0;
}

输出结果如下:

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

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

相关文章

RuoYi-Cloud诺依微服务项目

1、架构图 从图中解析出RuoYi-Cloud 使用微服务技术栈 网关&#xff1a;Gateway远程调用&#xff1a;Ribbon/Feign注册中心&#xff1a;Nacos Discovery熔断降级&#xff1a;Sentinel配置中心&#xff1a;Nacos Config链路追踪&#xff1a;Sleuth ZipKin/SkyWalking &#x…

leetcode(力扣) 89. 格雷编码 (规律题)

文章目录 题目描述思路分析完整代码 题目描述 n 位格雷码序列 是一个由 2n 个整数组成的序列&#xff0c;其中&#xff1a; 每个整数都在范围 [0, 2n - 1] 内&#xff08;含 0 和 2n - 1&#xff09; 第一个整数是 0 一个整数在序列中出现 不超过一次 每对 相邻 整数的二进制表…

vue3 使用antd 报错Uncaught TypeError--【已解决】

问题现象 使用最基本的 ant-design-vue 按钮demo 都报错 报错文字如下 Uncaught TypeError: Cannot read properties of undefined (reading value)at ReactiveEffect.fn (ant-design-vue.js?v597f5366:6693:87)at ReactiveEffect.run (chunk-K2VKR2AM.js?v25c381c3:461:…

用文本创建图表的工具PlantUML

什么是 PlantUML &#xff1f; PlantUML 是一种开源工具&#xff0c;允许用户从纯文本语言创建图表。除了各种 UML 图之外&#xff0c;PlantUML 还支持各种其他软件开发相关格式&#xff0c;以及 JSON 和 YAML 文件的可视化。PlantUML 语言是特定领域语言的一个示例。 什么是 P…

Shopee ERP:提升电商管理效率的终极解决方案

Shopee ERP&#xff08;Enterprise Resource Planning&#xff0c;企业资源规划&#xff09;是一款专为Shopee卖家设计的集成化电商管理软件。通过使用Shopee ERP系统&#xff0c;卖家可以更高效地管理他们的在线商店&#xff0c;实现库存管理、订单处理、物流跟踪、财务管理、…

【理论篇】SaTokenException: 非Web上下文无法获取Request问题解决 -理论篇

在我们使用sa-token安全框架的时候&#xff0c;有时候会提示&#xff1a;SaTokenException:非Web上下文无法获取Request 错误截图&#xff1a; 在官方网站中&#xff0c;查看常见问题排查&#xff1a; 错误追踪&#xff1a; 跟着源码可以看到如下代码&#xff1a; 从源码中&a…

【Spring教程30】Spring框架实战:从零开始学习SpringMVC 之 Rest风格简介与RESTful入门案例

目录 1 REST简介2 RESTful入门案例2.1 环境准备2.2 思路分析2.3 修改RESTful风格 3 知识点总结 欢迎大家回到《Java教程之Spring30天快速入门》&#xff0c;本教程所有示例均基于Maven实现&#xff0c;如果您对Maven还很陌生&#xff0c;请移步本人的博文《如何在windows11下安…

我的世界合成表大全(最新完整版)

我的世界合成表配方是什么? 我的世界是一款非常有趣的高自由度的沙盒游戏&#xff0c;游戏中玩家可以根据合成配方制作各种各样的物品。今天小编就为大家带来我的世界合成表大全(最新完整版)&#xff0c;希望可以帮到大家。 我的世界合成表大全(最新完整版) 基础物品合成表&a…

知识付费小程序开发:构建个性化学习平台的技术实践

随着在线学习和知识付费的兴起&#xff0c;开发一款知识付费小程序成为了创新的热点之一。本文将通过使用Node.js、Express和MongoDB为例&#xff0c;演示如何构建一个基础的知识付费小程序后端&#xff0c;并实现用户认证和知识内容管理。 1. 初始化项目 首先&#xff0c;确…

eNSP小实验(ACL和NAT)

一.ACL 实验目的&#xff1a;过滤流量&#xff0c;然后匹配规划后&#xff0c;判断该流量通过或拒绝 1.拓扑图 2.配置 基本ACL 其它同理配置 R1 [Huawei]sys R1 [R1]int g0/0/0 [R1-GigabitEthernet0/0/0]dis th [V200R003C00] # interface GigabitEthernet0/0/0 # return…

基础IO --- 下

目录 1. 理解文件系统中inode的概念 1.1. 了解磁盘 1.1.1. 认识磁盘 1.1.2. 磁盘的物理结构 1.1.3. 简单了解磁盘如何读写数据的 1.1.4. 磁头和盘面没有物理上的接触 1.1.5. 扇区的了解 1.1.6. 如何在物理上找到一个具体的扇区 1.2. 站在OS的角度看待磁盘 1.2.1. …

走进暄桐教室 一起观看暄桐同学作品及感受

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;旨在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。其实&#xff0c;暄桐教室…

Linux 系统 yum 安装 jdk1.8

1、首先检查是否存在jdk java -version上图这样就是系统没有找到已经安装的jdk 2.查看jdk版本列表 yum -y list java*执行此命令会显示所有版本 jdk 安装包 3、下载安装jdk 这里安装的是jdk1.8 yum install java-1.8.0-openjdk-devel.x86_64这里输入回车y继续安装 4、再次检…

低代码开发入局,同飞股份应用云表自主开发MES管理系统

近日&#xff0c;为了贯彻落实《“十四五”智能制造发展规划》&#xff0c;推动中国从制造大国向制造强国转变&#xff0c;工业和信息化部发布了2023年度“智能制造优秀场景”名单。经过省级有关部门和中央企业的推荐、专家评审、网上公示等程序&#xff0c;同飞股份凭借其“先…

LeetCode-反转链表问题

1.反转链表 题目描述&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 思路&#xff1a; 反转链表也就是链表倒置&#xff0c;我一直以来的办法就是先建立一个头节点&#xff0c;之后再遍历链表来进行头插。 代码&#xff1…

自动驾驶技术:驶向未来的智能之路

导言 自动驾驶技术正引领着汽车产业向着更安全、高效、智能的未来演进。本文将深入研究自动驾驶技术的核心原理、关键技术、应用场景以及对交通、社会的深远影响。 1. 简介 自动驾驶技术是基于先进传感器、计算机视觉、机器学习等技术的创新&#xff0c;旨在实现汽车在不需要人…

强化学习--免模型预测与控制

免模型预测与控制 强化学习 免模型预测与控制免模型预测蒙特卡洛估计时序差分估计时序产分与蒙特卡洛的比较免模型控制Q-learning 免模型预测 蒙特卡洛估计 蒙特卡洛估计方法在强化学习中是免模型预测价值函数的方式之一&#xff0c;本质是一种统计模拟方法&#xff0c;它的发…

Mac brew install youtube-dl 【 youtube 下载工具:youtube-dl 安装】

文章目录 1. 简介2. 预备3. 安装4. 命令5. 测试 1. 简介 youtube-dl - 从youtube.com或其他视频平台下载视频 https://github.com/ytdl-org/youtube-dl 2. 预备 安装并配置 git安装 brew 3. 安装 MacBook-Pro ~ % brew install youtube-dl Warning: youtube-dl has been …

mysql 索引场景 大于>为什么失效

可以先看这个&#xff1a;Mysql查询条件为大于时&#xff0c;不走索引失效场景-CSDN博客 改为> &#xff0c;可双看到key_len减少了&#xff0c;从90变到了86&#xff0c;也就是说联合索引(a b c) &#xff0c;只有(a b) 起了效果,c 没有。 可以不查c看看结果&#xff0c;还…

Leetcode—459.重复的子字符串【简单】

2023每日刷题&#xff08;五十九&#xff09; Leetcode—459.重复的子字符串 算法思想 巧解的算法思想 实现代码 从第一个位置开始到s.size()之前&#xff0c;看s字符串是否是ss的子串 class Solution { public:bool repeatedSubstringPattern(string s) {return (s s).fin…