热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据结构详解:带头双向循环链表及其代码实现

本文将详细介绍带头双向循环链表的基本概念和实现方法,包括结构体定义、链表创建、初始化、查找、插入、删除及打印等操作。

带头双向循环链表

  • 1. 带头双向循环链表介绍
  • 2. 代码实现带头双向循环链表
    • 2.1 创建结构体
    • 2.2 链表创建
    • 2.3 链表初始化(哨兵位)
    • 2.4 查找链表中某一元素的位置
    • 2.5 任意位置插入数据(在pos位置之前)
    • 2.6 任意位置删除数据
    • 2.7 打印链表
  • 3. 总结
1. 带头双向循环链表介绍

带头双向循环链表是一种特殊的链表结构,它包含一个哨兵节点,并且每个节点都包含指向前一个节点和后一个节点的指针。这种结构使得链表的操作更加灵活和高效。

2. 代码实现带头双向循环链表

2.1 创建结构体

首先,我们需要定义一个结构体来表示链表中的节点:


typedef int LTDataType; // 定义数据类型,可以随时更改

typedef struct ListNode {
    LTDataType data; // 节点数据
    struct ListNode* pre; // 指向前一个节点的指针
    struct ListNode* next; // 指向后一个节点的指针
} LSTNode; // 重命名结构体类型

2.2 链表创建

接下来,我们编写一个函数来创建新的节点:


LSTNode* BuyNode(LTDataType x) {
    LSTNode* newnode = (LSTNode*)malloc(sizeof(LSTNode));
    if (newnode == NULL) {
        perror("malloc fail");
        exit(-1);
    }
    newnode->data = x;
    newnode->next = NULL;
    newnode->pre = NULL;
    return newnode;
}

2.3 链表初始化(哨兵位)

为了方便后续操作,我们通常会在链表中添加一个哨兵节点:


LSTNode* Init() {
    LSTNode* phead = BuyNode(-1); // 初始化哨兵节点,数据为-1
    phead->pre = phead; // 哨兵节点的前指针指向自身
    phead->next = phead; // 哨兵节点的后指针指向自身
    return phead;
}

2.4 查找链表中某一元素的位置

我们可以编写一个函数来查找链表中某个特定元素的位置:


LSTNode* LSTFind(LSTNode* phead, LTDataType x) {
    assert(phead); // 哨兵节点不能为空
    LSTNode* cur = phead->next; // 从哨兵节点的下一个节点开始查找
    while (cur != phead) { // 循环链表,直到回到哨兵节点
        if (cur->data == x) {
            return cur; // 找到目标节点,返回该节点
        }
        cur = cur->next; // 继续查找下一个节点
    }
    return NULL; // 未找到目标节点,返回空
}

2.5 任意位置插入数据(在pos位置之前)

我们可以在指定位置之前插入一个新的节点:


void LSTInsert(LSTNode* pos, LTDataType x) {
    assert(pos); // 插入位置不能为空
    LSTNode* newnode = BuyNode(x); // 创建新节点
    LSTNode* prev = pos->pre; // 获取插入位置的前一个节点
    prev->next = newnode; // 更新前一个节点的后指针
    newnode->pre = prev; // 更新新节点的前指针
    newnode->next = pos; // 更新新节点的后指针
    pos->pre = newnode; // 更新插入位置的前指针
}

2.6 任意位置删除数据

我们也可以删除指定位置的节点:


void LSTErase(LSTNode* pos) {
    assert(pos); // 删除位置不能为空
    LSTNode* pos_pre = pos->pre; // 获取删除位置的前一个节点
    LSTNode* pos_next = pos->next; // 获取删除位置的后一个节点
    free(pos); // 释放删除节点的内存
    pos_pre->next = pos_next; // 更新前一个节点的后指针
    pos_next->pre = pos_pre; // 更新后一个节点的前指针
}

2.7 打印链表

最后,我们可以编写一个函数来打印链表中的所有节点:


void LSTPrint(LSTNode* phead) {
    assert(phead); // 哨兵节点不能为空
    LSTNode* cur = phead->next; // 从哨兵节点的下一个节点开始打印
    while (cur != phead) { // 循环链表,直到回到哨兵节点
        printf("%d ", cur->data); // 打印当前节点的数据
        cur = cur->next; // 移动到下一个节点
    }
}
3. 总结

带头双向循环链表通过引入哨兵节点,使得链表的插入和删除操作变得更加简单和高效。无论是头插、尾插、头删还是尾删,都可以借助哨兵节点轻松实现。希望本文能帮助你更好地理解和掌握这种数据结构。


推荐阅读
  • 本文探讨了如何使用pg-promise库在PostgreSQL中高效地批量插入多条记录,包括通过事务和单一查询两种方法。 ... [详细]
  • 深入浅出TensorFlow数据读写机制
    本文详细介绍TensorFlow中的数据读写操作,包括TFRecord文件的创建与读取,以及数据集(dataset)的相关概念和使用方法。 ... [详细]
  • 本文详细解析了2019年西安邀请赛中的一道树形动态规划题目——J题《And And And》。题目要求计算树中所有子路径异或值为0的集合数量,通过深入分析和算法优化,提供了高效的解决方案。 ... [详细]
  • 本文详细介绍了Linux内核中misc设备驱动框架的实现原理及应用方法,包括misc设备的基本概念、驱动框架的初始化过程、数据结构分析以及设备的注册与注销流程。 ... [详细]
  • 在 Redis 中,整数集合(IntSet)主要用于存储有序的整数集合。当集合中的所有元素均为整数且集合长度不超过512时,Redis 会自动使用 IntSet 来提高效率和节省内存。本文将详细介绍 IntSet 的结构及其工作原理。 ... [详细]
  • 本文探讨了在QT框架中如何有效遍历文件内容,并解决了一个常见的错误,即文件内容读取为空时弹窗无法正常显示的问题。 ... [详细]
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • Java 架构:深入理解 JDK 动态代理机制
    代理模式是 Java 中常用的设计模式之一,其核心在于代理类与委托类共享相同的接口。代理类主要用于为委托类提供预处理、过滤、转发及后处理等功能,以增强或改变原有功能的行为。 ... [详细]
  • 在使用MFC进行项目开发时,可能会遇到编译错误C2244,提示函数定义与现有声明不匹配。本文将详细介绍这一错误的原因及解决方案。 ... [详细]
  • 第十一章 Python基本数据类型及内置方法
    一、概述数据类型是用来记录事物状态的,而事物的状态是不断变化的(如:一个人年龄的增长(操作int类型),单个人名的修改(操作str类型),学生列表中增加学生(操作list类型)等) ... [详细]
  • 利用R语言进行股票价格数据的线性回归分析
    本文介绍了如何使用R语言对Excel中的股票价格数据集执行线性回归分析。通过具体的代码示例,展示了数据的导入、处理及模型构建的过程。 ... [详细]
  • 本文详细介绍了Java集合框架中的Collection体系,包括集合的基本概念及其与数组的区别。同时,深入探讨了Comparable和Comparator接口的区别,并分析了各种集合类的底层数据结构。最后,提供了如何根据需求选择合适的集合类的指导。 ... [详细]
  • 在MFC开发中,TreeCtrl控件因其强大的层次结构展示能力而被广泛应用,例如在资源管理器视图中。本文将详细介绍如何高效地利用TreeCtrl控件,包括设置属性、添加项目以及使用图像列表等技巧。 ... [详细]
  • 本文探讨了如何在Android应用中实现图片的保存至外部存储,并通过原生方式分享这些图片。主要介绍了保存图片的不同策略以及通过Intent进行文件分享的具体步骤。 ... [详细]
  • Microsoft即将发布WPF/E的CTP(Community Technology Preview)和SDK,标志着RIA(Rich Internet Application)技术的新里程碑。更多详情及下载链接请参见MSDN官方页面。 ... [详细]
author-avatar
輕風斬情絲
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有