C/C++ 双链表之逆序的实例详解

yizhihongxing

C/C++ 双链表之逆序的实例详解

本文将详细讲解如何使用 C/C++ 实现双链表的逆序操作,以及具体实现代码的细节。在这篇文章中,我们将会介绍双链表的概念以及如何实现双链表的逆序操作。

双链表的概念

双链表是一种链式存储数据的结构,它类似于单向链表,但每个节点有两个指针分别指向该节点的前驱节点和后继节点。由于它的链式存储结构,双链表灵活、高效,在许多应用场景中都被广泛使用。

双链表的逆序操作

双链表的逆序操作是将双链表的存储顺序从原来的正序调整为逆序的一种操作。在实际应用中,逆序操作也被广泛使用,它可以用于实现链式结构的反转、实现栈等其他数据结构。

下面是代码示例:

struct ListNode {
    int val;
    ListNode *prev;
    ListNode *next;
    ListNode(int x) : val(x), prev(NULL), next(NULL) {}
};

ListNode* reverseList(ListNode* head) {
    ListNode* curr = head;
    ListNode* prev = NULL;
    while (curr != NULL) {
        ListNode* next = curr->next;
        curr->next = prev;
        curr->prev = next; // 注意此处的修改,将 prev 指向 next 节点
        prev = curr;
        curr = next;
    }
    return prev;
}

在上面的代码中,我们定义了一个结构体 ListNode 表示双链表节点的数据结构,它包含三个成员变量:一个 val 表示该节点存储的值,以及两个指针 prevnext 分别指向该节点的前驱节点和后继节点。

我们还实现了一个名为 reverseList 的函数,该函数用于实现双链表的逆序操作。该函数的参数为指向链表头节点的指针 head,返回值为指向逆序后的链表头节点的指针。该函数的实现过程如下:

  1. 定义两个指针 currprev,初始时分别指向链表的头节点和 NULL。
  2. 遍历链表,对于遍历到的每个节点,执行以下操作:
  3. 定义指针 next,将其指向当前节点的后继节点 next = curr->next
  4. 修改节点的指针,将当前节点的后继指针 curr->next 指向其前驱节点 prev,将当前节点的前驱指针 curr->prev 指向其后继节点 next
  5. prev 指针指向当前节点 prev = curr
  6. curr 指针指向下一个节点 curr = next
  7. 遍历结束后,返回 prev 指针即为逆序后的链表头节点。

代码示例

下面是一个完整的代码示例,包含了链表的创建、打印、插入、删除、查找和逆序等常用操作。

#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *prev;
    ListNode *next;
    ListNode(int x) : val(x), prev(NULL), next(NULL) {}
};

class List {
public:
    List() {
        head = new ListNode(0);
        tail = new ListNode(0);
        head->next = tail;
        tail->prev = head;
    }

    ~List() {
        ListNode* curr = head;
        while (curr != NULL) {
            ListNode* next = curr->next;
            delete curr;
            curr = next;
        }
    }

    void print() {
        ListNode* curr = head->next;
        while (curr != tail) {
            cout << curr->val << " ";
            curr = curr->next;
        }
        cout << endl;
    }

    void insert(int val) {
        ListNode* node = new ListNode(val);
        node->prev = tail->prev;
        node->next = tail;
        tail->prev->next = node;
        tail->prev = node;
    }

    void remove(int val) {
        ListNode* curr = head->next;
        while (curr != tail) {
            if (curr->val == val) {
                curr->prev->next = curr->next;
                curr->next->prev = curr->prev;
                delete curr;
                break;
            }
            curr = curr->next;
        }
    }

    ListNode* find(int val) {
        ListNode* curr = head->next;
        while (curr != tail) {
            if (curr->val == val) {
                return curr;
            }
            curr = curr->next;
        }
        return NULL;
    }

    void reverse() {
        ListNode* curr = head->next;
        ListNode* prev = NULL;
        while (curr != tail) {
            ListNode* next = curr->next;
            curr->next = prev;
            curr->prev = next; // 注意此处的修改,将 prev 指向 next 节点
            prev = curr;
            curr = next;
        }
        head->next = prev;
        prev->prev = head;
    }

private:
    ListNode* head;
    ListNode* tail;
};

int main() {
    List list;
    list.insert(1);
    list.insert(2);
    list.insert(3);
    list.insert(4);
    list.insert(5);
    cout << "原链表:" << endl;
    list.print();
    list.remove(3);
    cout << "删除节点 3 后的链表:" << endl;
    list.print();
    ListNode* node = list.find(2);
    cout << "查找节点 2:" << endl;
    cout << node->val << endl;
    cout << "逆序后的链表:" << endl;
    list.reverse();
    list.print();
    return 0;
}

在上面的代码中,我们定义了一个名为 List 的链表类,该类封装了链表的创建、打印、插入、删除、查找和逆序等常用操作。通过该类,我们可以轻松地实现链表的基本功能。

总结

本文详细介绍了如何使用 C/C++ 实现双向链表的逆序操作,并提供了实现代码和相关示例。在实际应用中,逆序操作是实现链式结构的反转和栈等其他数据结构的关键操作之一。通过本文的学习,相信读者已经对双向链表和逆序操作有了更加深入的了解。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C/C++ 双链表之逆序的实例详解 - Python技术站

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

相关文章

  • Spring Boot 指定外部启动配置文件详解

    标题:Spring Boot 指定外部启动配置文件详解 简介:本篇文章主要介绍如何使用Spring Boot指定外部启动配置文件,让读者能够在实际开发中更好地利用Spring Boot的强大功能。 一、为什么需要指定外部启动配置文件? 在Spring Boot项目中,我们通常会使用application.properties(或者application.ym…

    other 2023年6月25日
    00
  • 深入了解Java File对象的使用

    深入了解Java File对象的使用 Java中的File类提供了对文件和目录的操作和管理。以下是关于Java File对象的使用的详细攻略。 1. 创建File对象 可以使用File类的构造函数来创建File对象,构造函数接受文件路径作为参数。 示例代码: File file = new File(\"path/to/file.txt\&quot…

    other 2023年10月15日
    00
  • coresight介绍篇

    以下是“coresight介绍篇”的完整攻略: coresight介绍篇 coresight是一种硬件调试和跟踪技术,它可以帮助我们在嵌入式系统中进行调试和性能分析。coresight技术包括硬件和软件两个部分,其中硬件部分包括调试接口和跟踪组件,软件部分包括驱动程序和工具。本攻略将详细讲解coresight技术的基本概念和使用方法。 coresight技术…

    other 2023年5月8日
    00
  • docker删除none

    什么是Docker? Docker是一种开源的容器化平台,可以帮助开发人员和系统管理员更轻松地构建、部署和运行应用程序。 什么是Docker none? 在Docker中,当容器被删除时,它们会留下一个名为“none”的镜像。这些镜像不包含任何文件,但它们会占用磁盘空间并且可能会导致Docker镜像列表变得混乱。 如何删除Docker none? 以下是在D…

    other 2023年5月7日
    00
  • win10系统电脑鼠标右键没有个性化选择怎么办 简单几步快速设置个性化

    下面是针对“win10系统电脑鼠标右键没有个性化选择怎么办”的详细攻略。 一、查看右键菜单选项 首先,右击桌面空白处,看看右键菜单中是否有“个性化”选项。 如果没有“个性化”选项,则可以按住Shift键,同时右击空白处,看看菜单中是否有“打开 Powershell 窗口”选项。 如果仍然没有“个性化”或“Powershell”选项,可能是系统出现了故障,需要…

    other 2023年6月27日
    00
  • PHP中全局变量global和$GLOBALS[]的区别分析

    PHP中全局变量global和$GLOBALS[]的区别分析 在PHP中,全局变量是在函数外部定义的变量,可以在整个脚本中访问。而global关键字和$GLOBALS数组都用于在函数内部访问全局变量,但它们有一些区别。 使用global关键字 global关键字用于在函数内部引用全局变量。它的使用方法是在函数内部使用global关键字声明需要引用的全局变量,…

    other 2023年7月28日
    00
  • meta标签设置(移动端)

    什么是meta标签? meta标签是HTML文档中的一种特殊标签,用于提供有关文档的元数据信息。在移动端网页开发中,meta标签可以用于设置网页的视口(viewport)、缩放比例、主题颜色等信息。 meta标签设置(移动端) 以下是在移动端网页开发中常用的meta标签设置: 设置视口(viewport) 视口是指用户在浏览器中看到的网页区域。在移动设备上,…

    other 2023年5月7日
    00
  • GoLang实现Viper库的封装流程详解

    GoLang实现Viper库的封装流程详解 什么是Viper库? Viper是一个开源的Go语言库,用于读取和设置配置信息。它目前支持环境变量、文件、命令行标志和默认值等方式来读取配置信息。Viper的主要特点包括: 支持多种配置文件格式,例如JSON、YAML、TOML、HCL、Java Properties等。 支持将配置信息设置为环境变量,便于在容器化…

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