golang,go,博客,开源,编程

数据结构-双向链表

Published on with 0 views and 0 comments

双向链表(Doubly Linked List)是一种链式数据结构,与单向链表不同,双向链表中的每个节点不仅包含指向下一个节点的指针(即 next),还包含指向前一个节点的指针(即 prev)。这种结构使得在链表中进行双向遍历更加方便。

双向链表的结构:

一个双向链表的节点通常包含以下三个部分:

  1. 数据域(data):存储节点的实际数据。
  2. 指向下一个节点的指针(next):指向链表中的下一个节点。
  3. 指向前一个节点的指针(prev):指向链表中的前一个节点。

双向链表的优势:

  • 双向遍历:可以从头到尾遍历,也可以从尾到头遍历。
  • 删除操作:删除节点时不需要从头遍历,能够直接通过 prev 指针找到前一个节点,相对单向链表效率更高。

双向链表的操作:

  1. 插入操作
    • 在链表的头部插入节点。
    • 在链表的尾部插入节点。
    • 在链表的中间插入节点。
  2. 删除操作
    • 删除头节点。
    • 删除尾节点。
    • 删除中间的某个节点。
  3. 查找操作
    • 查找指定数据的节点。

双向链表的示意图:

  Head <-> Node1 <-> Node2 <-> Node3 <-> Tail

在这个示意图中:

  • Head 是链表的头节点。
  • Tail 是链表的尾节点。
  • 每个节点通过 nextprev 指针连接。

示例:双向链表节点结构(C++实现)

#include <iostream>
using namespace std;

// 双向链表节点
struct Node {
    int data;       // 节点数据
    Node* next;     // 指向下一个节点
    Node* prev;     // 指向前一个节点
};

// 双向链表类
class DoublyLinkedList {
public:
    Node* head;   // 链表头指针
    Node* tail;   // 链表尾指针

    DoublyLinkedList() {
        head = nullptr;
        tail = nullptr;
    }

    // 在尾部插入新节点
    void append(int value) {
        Node* newNode = new Node();
        newNode->data = value;
        newNode->next = nullptr;
        newNode->prev = tail;

        if (tail != nullptr) {
            tail->next = newNode;
        }
        tail = newNode;

        if (head == nullptr) {
            head = newNode;
        }
    }

    // 打印链表(从头到尾)
    void printForward() {
        Node* temp = head;
        while (temp != nullptr) {
            cout << temp->data << " ";
            temp = temp->next;
        }
        cout << endl;
    }

    // 打印链表(从尾到头)
    void printBackward() {
        Node* temp = tail;
        while (temp != nullptr) {
            cout << temp->data << " ";
            temp = temp->prev;
        }
        cout << endl;
    }
};

int main() {
    DoublyLinkedList list;
    list.append(10);
    list.append(20);
    list.append(30);

    cout << "Forward: ";
    list.printForward();

    cout << "Backward: ";
    list.printBackward();

    return 0;
}

双向链表的时间复杂度:

  • 插入操作:O(1)(如果我们已经知道插入的位置,比如在头部或尾部)。
  • 删除操作:O(1)(对于已知节点的删除,尤其是在尾部或头部)。
  • 查找操作:O(n)(由于没有索引,需要线性扫描)。

希望这些内容能帮助你理解双向链表!如果有更具体的疑问或应用场景,欢迎继续提问。


标题:数据结构-双向链表
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/10/1736470869666.html
联系:scotttu@163.com