C++双向链表的增删查改操作方法讲解

关于C++双向链表的增删查改操作方法,一般可以分为以下几步:

第一步:定义链表结构体

我们都知道链表是一种动态数据结构,它的每个元素都包含指向前一个元素和后一个元素的指针。因此,在C++中,我们可以用结构体来定义一个链表节点,具体的定义如下:

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

其中,val是节点的值,prev和next分别指向前一个节点和后一个节点。在这里,我们使用nullptr来初始化指针。

第二步:实现链表的增加操作

链表的增加操作也可以分为头插和尾插两种方式。

头插法

头插法是将新节点插入到链表的头部。具体的实现如下:

void addAtHead(ListNode*& head, int val) {
     ListNode* node = new ListNode(val);
     if (!head) {
         head = node;
     } else {
         node->next = head;
         head->prev = node;
         head = node;
     }
}

第一行代码是创建一个新的节点。如果链表为空,则将这个新节点设置为头节点。如果链表不为空,则将这个新节点插入到头节点的前面,并更新头节点的信息。

尾插法

尾插法是将新节点插入到链表的尾部。具体的实现如下:

void addAtTail(ListNode*& head, int val) {
    ListNode* node = new ListNode(val);
    if (!head) {
        head = node;
    } else {
        ListNode* cur = head;
        while (cur->next) {
            cur = cur->next;
        }
        cur->next = node;
        node->prev = cur;
    }
}

第一行代码同样是创建一个新的节点。如果链表为空,则将这个新节点设置为头节点。如果链表不为空,则从头节点开始遍历到链表尾部,在尾节点的后面加入一个新节点。

第三步:实现链表的删除操作

链表的删除操作也可以分为删除头节点和删除尾节点两种方式。

删除头节点

删除头节点可以直接将头节点的后一个节点作为头节点,并释放原头节点的内存空间。具体的实现如下:

void deleteAtHead(ListNode*& head) {
    if (!head) {
        return;
    }
    ListNode* tmp = head;
    head = head->next;
    if (head) {
        head->prev = nullptr;
    }
    delete tmp;
}

如果链表不为空,则将头节点指针指向第二个节点。由于新的头节点的前面没有节点,因此将它的prev指针置空。最后,释放掉原来的头节点的内存空间。

删除尾节点

删除尾节点可以遍历到尾节点的前一个节点,并将它的next指针置空。然后,释放掉原尾节点的内存空间。具体的实现如下:

void deleteAtTail(ListNode*& head) {
    if (!head) {
        return;
    }
    if (!head->next) {
        delete head;
        head = nullptr;
        return;
    }
    ListNode* cur = head;
    while (cur->next) {
        cur = cur->next;
    }
    cur->prev->next = nullptr;
    delete cur;
}

如果链表只有一个节点,直接释放掉这个节点并将头指针置空。否则从头节点开始遍历到尾节点的前一个节点,并释放掉尾节点的内存空间。

第四步:实现链表的查找操作

链表的查找操作主要是根据节点的值进行查找。我们可以从头节点开始遍历每个节点,如果找到了对应的节点,则返回该节点的指针。否则,返回nullptr。具体的实现如下:

ListNode* search(ListNode* head, int val) {
    while (head) {
        if (head->val == val) {
            return head;
        }
        head = head->next;
    }
    return nullptr;
}

从头节点开始遍历每个节点,如果找到了节点的值等于val,则返回该节点的指针。否则,继续向后遍历,直到链表的末尾都没有找到节点,则返回nullptr。

第五步:实现链表的修改操作

修改链表中的节点可以直接通过访问节点的val来修改。具体的实现如下:

void update(ListNode* head, int oldVal, int newVal) {
    ListNode* node = search(head, oldVal);
    if (node) {
        node->val = newVal;
    }
}

从头节点开始查找节点的值等于oldVal的节点。如果找到了节点,则将该节点的值修改为newVal。

示例说明

示例一

通过头插法构建一个链表,并输出该链表的值。

ListNode* head = nullptr;
addAtHead(head, 1);
addAtHead(head, 2); 
addAtHead(head, 3); 

ListNode* cur = head;
while (cur) {
    cout << cur->val << " ";
    cur = cur->next;
}

输出结果为“3 2 1”。

示例二

通过尾插法构建一个链表,并删除尾节点。

ListNode* head = nullptr;
addAtTail(head, 1);
addAtTail(head, 2); 
addAtTail(head, 3); 

deleteAtTail(head);

ListNode* cur = head;
while (cur) {
    cout << cur->val << " ";
    cur = cur->next;
}

输出结果为“1 2”。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++双向链表的增删查改操作方法讲解 - Python技术站

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

相关文章

  • C++进阶练习删除链表的倒数第N个结点详解

    C++进阶练习删除链表的倒数第N个结点详解 问题描述 给定一个单向链表的头指针和一个整数 n,要求删除这个链表的倒数第 n 个节点。例如,链表为 1→2→3→4→5,n = 2 时,删除倒数第二个节点后的链表为 1→2→3→5。 解法思路 先让一个指针指向链表头节点,再让另一个指针从头节点开始向后移动 n-1 步,此时两个指针之间有 n-1 个节点。然后同时…

    other 2023年6月27日
    00
  • ubuntu环境变量设置方法分享

    下面是详细讲解“ubuntu环境变量设置方法分享”的完整攻略。 环境变量是什么 环境变量是操作系统定义的一些全局变量,主要用于在所有进程中存储以供访问的值。在 Ubuntu 中,环境变量通常用于指定一些重要的系统路径和配置信息,例如 PATH、JAVA_HOME 等。 查看当前环境变量 在 Ubuntu 终端中,我们可以使用 echo $PATH 命令查看当…

    other 2023年6月27日
    00
  • JavaScript Class类实例讲解

    标题: JavaScript Class类实例讲解 正文: 在JavaScript中,利用类(Class)可以很方便地定义对象及其属性与方法。本文将介绍如何定义类、创建类的实例,以及如何使用类、继承类等相关操作。 1. 定义类 类定义可以采用class关键字来完成。类定义的基本格式如下: class MyClass { // 属性 a = 1; b = 2;…

    other 2023年6月27日
    00
  • PHP对象实例化单例方法

    PHP对象实例化单例方法是一种常用的设计模式,其主要目的是确保类在整个运行时期内最多只能有一个实例,并且提供一种全局可访问该实例的方式。下面我将为您详细讲解如何实现PHP对象实例化单例方法。 第一步:私有化构造函数和克隆函数 为了保证只有一个实例,我们需要将构造函数设为私有,防止外部通过new操作符创建新的实例。同时,我们还需要将克隆函数设为私有,防止通过c…

    other 2023年6月26日
    00
  • 数学建模–优劣解距离法

    以下是关于“数学建模-优劣解距离法”的完整攻略,过程中包含两个示例。 背景 优劣解距离法是一种用于多目标优化问题的解方法。它可以用于一组解的优劣程度,并找到最优解。在本攻略中,我们将介绍如何使用优劣解距离法来解决目标优化问题。 基本原理 优劣解距离法的基本原理通过计算每个解与最优解之间的距离来确定每个解的优劣程度。具体步骤如下: 确定多个目标函数。 计算每个…

    other 2023年5月9日
    00
  • AirPods Pro一直断连怎么办 AirPods Pro连接不稳定的解决办法

    AirPods Pro一直断连怎么办 如果你的 AirPods Pro 经常断连,可以尝试以下解决方法。 1. 确认设备连接状态 首先,请确保你的设备(如 iPhone、iPad 或 Mac)已经完成了与 AirPods Pro 的连接过程。然后,打开设置中的蓝牙,确认 AirPods Pro 已经成功连接。如果连接不成功,请尝试将 AirPods Pro …

    other 2023年6月27日
    00
  • Spring核心之IOC与bean超详细讲解

    当然!下面是关于\”Spring核心之IOC与Bean超详细讲解\”的完整攻略,包含两个示例说明。 … … … … … … … … … … … … … … … … … … … … … … … … … … … … … … … … ..…

    other 2023年8月20日
    00
  • Kotlin之在Gradle中无参(no-arg)编译器插件的使用详解

    下面我将详细讲解Kotlin在Gradle中无参(no-arg)编译器插件的使用,包含以下内容: 为什么需要无参编译器插件? 如何使用无参编译器插件? 示例说明。 为什么需要无参编译器插件? 在使用Kotlin编写Java框架时,我们经常需要生成一些无参构造函数,以便能够在框架中使用反射来创建对象。但是,由于Kotlin的默认构造函数参数是必须的,编译器不会…

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