C++零基础精通数据结构之带头双向循环链表

C++零基础精通数据结构之带头双向循环链表

什么是带头双向循环链表?

带头双向循环链表是一个常见的数据结构,它可以用来实现链表和队列等数据结构。带头双向循环链表的特点是:

  1. 每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。
  2. 链表中有一个头节点,但是它不存储数据。
  3. 链表的尾节点指向头节点,头节点的前一个节点指向链表的尾节点。这样就形成了一个循环。

怎样实现带头双向循环链表?

带头双向循环链表的节点结构体

struct Node {
    int data;
    Node* prev;
    Node* next;
};

节点包含一个数据域 data,以及两个指针 prevnext

初始化带头双向循环链表

Node* init() {
    Node* head = new Node;         // 创建头节点
    head->prev = head;            // 头节点的上一个节点是头节点自身
    head->next = head;            // 头节点的下一个节点是头节点自身
    return head;                  // 返回头节点
}

初始化带头双向循环链表,先创建一个头节点,然后让头节点的上一个指针和下一个指针都指向自身,最后返回头节点。

判断带头双向循环链表是否为空

bool isEmpty(Node* head) {
    return head->next == head;
}

如果头节点的下一个节点指向头节点自身,说明链表为空,返回 true

在带头双向循环链表尾部插入一个节点

void insertAtTail(Node* head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->prev = head->prev;   // 新节点的上一个节点是原链表的尾节点
    newNode->next = head;         // 新节点的下一个节点是头节点
    head->prev->next = newNode;   // 原链表的尾节点的下一个节点是新节点
    head->prev = newNode;         // 头节点的上一个节点是新节点
}

创建一个新节点,将它的数据域和上一个指针赋值,然后将它的下一个指针指向头节点,接着将原链表的尾节点的下一个指针指向新节点,最后将头节点的上一个指针指向新节点。

在带头双向循环链表头部插入一个节点

void insertAtHead(Node* head, int data) {
    Node* newNode = new Node;
    newNode->data = data;
    newNode->prev = head;         // 新节点的上一个节点是头节点
    newNode->next = head->next;   // 新节点的下一个节点是原链表的头节点
    head->next->prev = newNode;   // 原链表的头节点的上一个节点是新节点
    head->next = newNode;         // 头节点的下一个节点是新节点
}

创建一个新节点,将它的数据域和下一个指针赋值,然后将它的上一个指针指向头节点,接着将原链表的头节点的上一个指针指向新节点,最后将头节点的下一个指针指向新节点。

删除节点

void remove(Node* head, int data) {
    Node* p = head->next;
    while (p != head && p->data != data) {   // 找到要删除的节点
        p = p->next;
    }
    if (p != head) {
        p->prev->next = p->next;   // 上一个节点的下一个指针指向下一个节点
        p->next->prev = p->prev;   // 下一个节点的上一个指针指向上一个节点
        delete p;                  // 释放被删除的节点的内存
    }
}

先找到要删除的节点,然后将它的上一个节点的下一个指针指向它的下一个节点,将它的下一个节点的上一个指针指向它的上一个节点,最后释放它的内存。

示例说明

示例1:插入数据、遍历数据、删除数据

int main() {
    Node* head = init();                  // 初始化带头双向循环链表
    insertAtTail(head, 1);                // 在尾部插入1
    insertAtTail(head, 2);                // 在尾部插入2
    insertAtHead(head, 0);                // 在头部插入0
    insertAtTail(head, 3);                // 在尾部插入3
    insertAtTail(head, 4);                // 在尾部插入4

    Node* p = head->next;                 // 遍历链表
    while (p != head) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;

    remove(head, 1);                      // 删除1

    p = head->next;                       // 遍历链表
    while (p != head) {
        cout << p->data << " ";
        p = p->next;
    }
    cout << endl;

    return 0;
}

输出结果:

0 1 2 3 4
0 2 3 4

示例2:插入数据、判断链表是否为空

int main() {
    Node* head = init();                  // 初始化带头双向循环链表
    insertAtTail(head, 1);                // 在尾部插入1
    insertAtTail(head, 2);                // 在尾部插入2

    if (isEmpty(head)) {                  // 判断链表是否为空
        cout << "链表为空" << endl;
    } else {
        cout << "链表不为空" << endl;
    }

    return 0;
}

输出结果:

链表不为空

至此,带头双向循环链表的初始化、插入、删除、遍历和判断是否为空的基本操作都已经讲解完毕。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++零基础精通数据结构之带头双向循环链表 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 使用navicat导入excel表

    使用Navicat导入Excel表 Navicat是一款强大的数据库管理工具,它包含了许多实用的功能,其中之一就是能够导入Excel表。在本篇文章中,我们将介绍如何使用Navicat导入Excel表。 步骤一:打开Navicat 首先打开Navicat,连接到你的数据库。 步骤二:选择数据库 在连接成功后,选择需要导入Excel表的数据库。 步骤三:选择表 …

    其他 2023年3月28日
    00
  • 新安装的XAMPP访问phpmyadmin出错的解决方法

    如果你新安装的XAMPP出现了访问phpmyadmin出错的问题,一般有以下两种可能的解决方法: 方法一:重启Apache和MySQL服务 有时候出错的原因可能是因为Apache和MySQL服务没有正常启动,所以你可以尝试通过重启这两个服务来解决此问题。具体步骤如下: 在XAMPP控制面板中,停止Apache和MySQL服务 点击“Start”按钮,再次启动…

    other 2023年6月26日
    00
  • 无效的源发行版:11和无效的目标发行版:11解决方法

    当在Ubuntu系统中使用apt-get命令安装软件包时,有时会遇到“无效的源发行版:11”或“无效的目标发行版:11”等错误。这些错误通常是由于软件源配置不正确或系统版本不兼容导致的。在攻略中,我们将介绍如何解决这些错误。 无效的源发行版11 如果您在使用apt-get命令时遇“无效的源发行版:11”错误,可以按照以下步骤解决: 打开终端并输入以下命令: …

    other 2023年5月9日
    00
  • VueJs中如何使用Teleport及组件嵌套层次结构详解

    VueJs中如何使用Teleport及组件嵌套层次结构详解 在Vue.js中,Teleport是一个强大的特性,它允许我们将组件的内容渲染到DOM中的任意位置,而不仅仅是组件所在的位置。这对于创建复杂的组件嵌套层次结构非常有用。下面是如何使用Teleport及组件嵌套层次结构的详细攻略。 Teleport的基本用法 Teleport的基本用法非常简单。我们可…

    other 2023年7月27日
    00
  • java微信开发API第一步 服务器接入

    下面我将详细讲解Java微信开发API第一步——服务器接入的完整攻略。 一、准备工作 在进行微信开发之前,需要先进行微信公众号或小程序的注册和开发者资质认证。开发者资质认证通过后,即可进入公众号后台或小程序管理后台,完成服务器配置。 二、服务器配置 1. 服务器搭建 首先,我们需要在服务器上搭建一个运行中的web服务,推荐使用Spring MVC、JFina…

    other 2023年6月26日
    00
  • 靠谱助手解决常见安卓模拟器的四大无法安装问题

    下面是“靠谱助手解决常见安卓模拟器的四大无法安装问题”的完整攻略: 一、问题描述 在使用安卓模拟器过程中,有时会遇到无法安装软件的问题。主要表现为点击安装软件后,无反应或弹出提示框但无法正常安装软件。这个问题会给用户带来很大的不便,特别是对于安卓开发人员来说更是一个重要问题。 二、常见原因 下面列举常见的四个原因:1. 当前模拟器内存不足,或存储空间不足;2…

    other 2023年6月26日
    00
  • 鼠标键盘时好时坏怎么用键盘代替应付简单操作?

    当鼠标或者键盘遇到问题时,我们可以使用键盘来代替鼠标完成简单的操作,而不会受到太大的影响。下面是具体的攻略: 1. 使用Tab键进行焦点转移 当鼠标无法正常使用时,我们可以使用Tab键来进行焦点转移,通过Tab键可以在网页的各个部分进行移动,选中需要的元素。常用的几个Tab键使用场景如下: 在网页中倒序移动到后面的元素,可以使用Shift + Tab 在表单…

    other 2023年6月27日
    00
  • pcb录屏工具screen2exegifcamscreentogif

    以下是PCB录屏工具Screen2ExeGifCamScreenToGif的攻略: 步骤1:了解Screen2ExeGifCamScreenToGif Screen2ExeGifCamScreenToGif是一款PCB屏工具,可以用于录制屏幕、制作GIF动画和生成执行文件。工具具有简单易用的界面和丰富的功能,可以满足不同用户的需求。 步骤2:使用Screen…

    other 2023年5月6日
    00
合作推广
合作推广
分享本页
返回顶部