C++数据结构之双向链表

C++数据结构之双向链表完整攻略

1. 什么是双向链表

双向链表是一种特殊的链表结构,每个节点拥有两个指针域,分别指向前继和后继节点。

双向链表不需要像单向链表那样从头到尾遍历整个链表,可以通过前后指针直接访问前后节点,提高了查找、删除、插入等操作的效率。

双向链表有一些常用的操作,如插入节点、删除节点、查找节点等。

2. 双向链表的实现

2.1 节点定义

template <typename T>
struct DListNode {
    T data;
    DListNode<T> *prev; // 指向前继节点指针
    DListNode<T> *next; // 指向后继节点指针
};

2.2 双向链表类定义

template <typename T>
class DLinkedList {
public:
    DLinkedList() : _head(nullptr), _tail(nullptr), _size(0) {}
    ~DLinkedList() {}

    // 插入操作
    void insertFront(T value);          // 在头部插入节点
    void insertBack(T value);           // 在尾部插入节点
    void insertAt(DListNode<T> *node, T value); // 在指定位置之后插入节点

    // 删除操作
    void deleteFront();  // 删除头部节点
    void deleteBack();   // 删除尾部节点
    void deleteAt(DListNode<T> *node); // 删除单个节点

    // 查找操作
    DListNode<T> *find(T value); // 根据值查找节点
    DListNode<T> *findAt(int index); // 根据下标查找节点

    // 判空操作
    bool empty() { return _head == nullptr; }

    // 返回链表长度
    int size() { return _size; }

    // 输出链表
    void print();

private:
    DListNode<T> *_head; // 头指针
    DListNode<T> *_tail; // 尾指针
    int _size;           // 链表长度
};

2.3 插入节点操作

在头部插入节点,实现如下:

template <typename T>
void DLinkedList<T>::insertFront(T value) {
    DListNode<T> *newNode = new DListNode<T>();
    newNode->data = value;

    if (empty()) {
        _tail = newNode; // 如果链表为空,插入后的节点即为尾节点
    } else {
        _head->prev = newNode;
    }

    newNode->next = _head;
    _head = newNode;
    ++_size;
}

在尾部插入节点,实现如下:

template <typename T>
void DLinkedList<T>::insertBack(T value) {
    DListNode<T> *newNode = new DListNode<T>();
    newNode->data = value;

    if (empty()) {
        _head = newNode; // 如果链表为空,插入后的节点即为头节点
    } else {
        _tail->next = newNode;
    }

    newNode->prev = _tail;
    _tail = newNode;
    ++_size;
}

在指定位置插入节点,实现如下:

template <typename T>
void DLinkedList<T>::insertAt(DListNode<T> *node, T value) {
    DListNode<T> *newNode = new DListNode<T>();
    newNode->data = value;

    newNode->prev = node;
    newNode->next = node->next;
    node->next = newNode;

    if (node == _tail) {
        _tail = newNode;
    } else {
        newNode->next->prev = newNode;
    }

    ++_size;
}

2.4 删除节点操作

删除头部节点,实现如下:

template <typename T>
void DLinkedList<T>::deleteFront() {
    if (empty()) {
        return;
    }

    DListNode<T> *node = _head;

    _head = node->next;
    if (_head != nullptr) {
        _head->prev = nullptr;
    } else {
        _tail = nullptr;
    }

    delete node;
    --_size;
}

删除尾部节点,实现如下:

template <typename T>
void DLinkedList<T>::deleteBack() {
    if (empty()) {
        return;
    }

    DListNode<T> *node = _tail;
    _tail = node->prev;
    if (_tail != nullptr) {
        _tail->next = nullptr;
    } else {
        _head = nullptr;
    }

    delete node;
    --_size;
}

删除任意节点,实现如下:

template <typename T>
void DLinkedList<T>::deleteAt(DListNode<T> *node) {
    if (node == nullptr) {
        return;
    }

    if (node->prev == nullptr) {
        deleteFront();
    } else if (node->next == nullptr) {
        deleteBack();
    } else {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        delete node;
        --_size;
    }
}

2.5 查找节点操作

根据值查找节点,实现如下:

template <typename T>
DListNode<T> *DLinkedList<T>::find(T value) {
    DListNode<T> *node = _head;

    while (node != nullptr) {
        if (node->data == value) {
            return node;
        }
        node = node->next;
    }

    return nullptr;
}

根据下标查找节点,实现如下:

template <typename T>
DListNode<T> *DLinkedList<T>::findAt(int index) {
    if (index >= size()) {
        return nullptr;
    }

    DListNode<T> *node = _head;
    int i = 0;

    while (node != nullptr && i < index) {
        node = node->next;
        ++i;
    }

    return node;
}

2.6 输出链表操作

template <typename T>
void DLinkedList<T>::print() {
    DListNode<T> *node = _head;
    while (node != nullptr) {
        cout << node->data << " ";
        node = node->next;
    }
    cout << endl;
}

3. 示例说明

3.1 实现双向链表并遍历

int main() {
    DLinkedList<int> list;

    // 在头尾插入节点
    list.insertFront(1);
    list.insertBack(2);

    // 在头部插入节点,使链表变为 3 1 2
    DListNode<int> *node = list.find(1);
    list.insertAt(node, 3);

    // 删除尾部节点,使链表变为 3 1
    list.deleteBack();

    // 遍历输出链表
    list.print();

    return 0;
}

输出结果:

3 1

3.2 按下标查找节点并删除

int main() {
    DLinkedList<int> list;

    // 在头尾插入节点
    list.insertFront(1);
    list.insertBack(2);

    // 在头部插入节点,使链表变为 3 1 2
    DListNode<int> *node = list.find(1);
    list.insertAt(node, 3);

    // 删除下标为 1 的节点,即 1,使链表变为 3 2
    node = list.findAt(1);
    list.deleteAt(node);

    // 遍历输出链表
    list.print();

    return 0;
}

输出结果:

3 2

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

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构中定位函数Index的使用方法

    C语言的数据结构中,定位函数Index的使用方法主要涉及到数组和指针的相关操作。Index函数的作用是在数组中查找对应的元素,返回该元素的索引位置。以下是详细攻略: 一、Index函数的用法 Index函数的原型如下: void *index(const void *s, int c, size_t n); 其中,参数含义如下: s: 要查找的数组 c: 要…

    数据结构 2023年5月17日
    00
  • C++数据结构之list详解

    C++数据结构之list详解 什么是list? list是C++ STL库中的一个数据结构,它能够以O(1)的复杂度在任何位置进行插入或删除操作,当然它也支持随机访问指定位置的元素。list属于双向链表,它内部结构为指针连接不同的节点。 如何使用list? 包含头文件 在C++中使用list,需要包含头文件#include <list>。 定义l…

    数据结构 2023年5月17日
    00
  • Python内存管理器如何实现池化技术

    Python内存管理器使用了池化技术来进行内存管理,这使得Python程序的内存管理效率比较高。下面我将详细介绍Python内存管理器如何实现池化技术: 1. 内存分配 Python内存管理器在Python运行时,会维护多个大小不同的内存块池,每个池的大小相同。当Python程序需要分配内存时,会首先在池中寻找是否有剩余内存块可以分配。如果有,则分配给程序使…

    数据结构 2023年5月17日
    00
  • Android开发数据结构算法ArrayList源码详解

    Android开发数据结构算法ArrayList源码详解 概述 Android开发中,大量使用到了数据结构和算法,ArrayList便是其中的一种非常重要的数据结构。ArrayList是Java中非常重要且使用率非常高的一种数据结构,Android开发中也经常使用它来存储数据。本文将深入探究ArrayList的源码,帮助读者更好地理解其工作原理和使用方法。 …

    数据结构 2023年5月17日
    00
  • Java数据结构之稀疏数组的实现与应用

    Java数据结构之稀疏数组的实现与应用 什么是稀疏数组 稀疏数组是一种刻画二维数组中许多元素值都为0的特殊数据结构。它可以提高存储空间的利用率,实现对数据的压缩和优化,减少不必要的处理,提升程序的运行效率。 在稀疏数组中,只有非零元素被存储,而这些元素的索引信息和具体数值的信息都会被记录下来。 稀疏数组的实现与应用 实现步骤 创建原始的二维数组,存入多个元素…

    数据结构 2023年5月17日
    00
  • C++数据结构之红黑树的实现

    《C++数据结构之红黑树的实现》是一篇介绍红黑树实现的文章,通过本文,你可以了解到什么是红黑树以及如何实现红黑树。 什么是红黑树 红黑树是一种自平衡的二叉查找树,它具有良好的平衡性和查找性能。红黑树可以在O(log n)的时间内完成查找、插入和删除操作。 红黑树的一个重要性质是它的任何一个节点都有一个颜色(红色或黑色)属性。在插入、删除操作中,需要通过一定的…

    数据结构 2023年5月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • js实现无限层级树形数据结构(创新算法)

    要实现无限层级树形数据结构,可以使用递归算法来解决。以下是该过程的详细攻略: 步骤1:准备数据 为了演示无限层级树形结构,我们需要准备一组具有父子关系的数据。数据可以是任何格式,例如在子对象节点下添加一个名为children的数组即可。 例如,假设我们有以下数据: const data = [ { id: 1, name: "Node 1&quot…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部