📜  使用双向链表实现Deque(1)

📅  最后修改于: 2023-12-03 15:06:55.488000             🧑  作者: Mango

使用双向链表实现Deque

双向链表是一种常见的数据结构,它可以用于实现Deque(双端队列)。Deque是一种特殊的队列,可以从队列的两端进行入队和出队操作。

双向链表的每个节点除了有指向下一个节点的指针外,还有指向上一个节点的指针。这样,我们可以从任意一个节点开始,沿着两个方向遍历整个链表。

下面,我们来介绍如何使用双向链表实现Deque。

实现思路

我们可以使用两个指针来分别指向Deque的头和尾。入队时,把新元素插入到头指针的前面;出队时,从尾指针的后面取出元素。双向链表的insert和delete操作可以很方便地实现这种操作。

具体来说,我们需要维护如下几个指针:

  • head:指向Deque的头部节点的指针。
  • tail:指向Deque的尾部节点的指针。
  • first:指向Deque中第一个元素的指针。
  • last:指向Deque中最后一个元素的指针。

入队操作分两步:

  1. 创建一个新节点,将新的元素作为节点值;
  2. 将新节点插入到head指针的前面。

出队操作分两步:

  1. 获取tail指针的后一个节点的值;
  2. 删除tail指针指向的节点。

其他的操作包括:

  • 获取Deque的头元素和尾元素;
  • 判断Deque是否为空;
  • 获取Deque中元素的个数;
  • 清空Deque。
代码实现

下面是基于双向链表的Deque的实现,使用C++语言编写:

#include <iostream>

using namespace std;

template<typename T>
class Deque {
private:
    struct Node {
        T value;    // 元素值
        Node *next; // 后继指针
        Node *prev; // 前驱指针

        Node(T value, Node *next=nullptr, Node *prev=nullptr)
            : value(value), next(next), prev(prev) {}
    };

    Node *head; // 头指针
    Node *tail; // 尾指针
    Node *first; // 第一个元素指针
    Node *last; // 最后一个元素指针
    int size; // 队列大小
public:
    Deque() : head(nullptr), tail(nullptr), first(nullptr), last(nullptr), size(0) {}

    bool empty() const {
        return size == 0;
    }

    int getSize() const {
        return size;
    }

    T& front() {
        if (empty()) {
            throw "Deque is empty!";
        }
        return first->value;
    }

    T& back() {
        if (empty()) {
            throw "Deque is empty!";
        }
        return last->value;
    }

    void push_front(const T& value) {
        Node *node = new Node(value, head, nullptr);
        if (empty()) {
            tail = node;
            last = node;
        } else {
            head->prev = node;
        }
        head = node;
        first = node;
        size++;
    }

    void push_back(const T& value) {
        Node *node = new Node(value, nullptr, tail);
        if (empty()) {
            head = node;
            first = node;
        } else {
            tail->next = node;
        }
        tail = node;
        last = node;
        size++;
    }

    void pop_front() {
        if (empty()) {
            throw "Deque is empty!";
        }
        Node *temp = head;
        head = head->next;
        first = head;
        delete temp;
        if (head == nullptr) {
            tail = nullptr;
            last = nullptr;
        } else {
            head->prev = nullptr;
        }
        size--;
    }

    void pop_back() {
        if (empty()) {
            throw "Deque is empty!";
        }
        Node *temp = tail;
        tail = tail->prev;
        last = tail;
        delete temp;
        if (tail == nullptr) {
            head = nullptr;
            first = nullptr;
        } else {
            tail->next = nullptr;
        }
        size--;
    }

    void clear() {
        while (!empty()) {
            pop_front();
        }
    }
};
总结

本文介绍了使用双向链表实现Deque的思路和具体的实现。虽然不同编程语言的实现方式可能不同,但基本思路是相似的。使用双向链表实现Deque可以实现O(1)的时间复杂度,比使用数组实现Deque更加高效。