返回

双向链表与双向循环链表之间的关系和区别

IOS

双向链表和双向循环链表:深入比较和应用

简介

双向链表和双向循环链表都是数据结构中的基石,它们在各种算法和应用中发挥着至关重要的作用。在这篇文章中,我们将深入探讨它们之间的关系、区别、实现方法和应用场景。

双向链表和双向循环链表的关系

双向链表和双向循环链表都是链表,由包含数据和指针的节点组成。在双向链表中,每个节点都有一个指向其后继节点的指针和一个指向其前驱节点的指针。而在双向循环链表中,每个节点也有一个指向其后继节点的指针和一个指向其前驱节点的指针,但尾节点的 next 指针指向头节点,头节点的 prev 指针指向尾节点,形成一个循环。

双向链表和双向循环链表的区别

双向链表和双向循环链表的主要区别在于尾节点的 next 指针和头节点的 prev 指针指向不同。在双向链表中,尾节点的 next 指针指向 null,头节点的 prev 指针也指向 null。而在双向循环链表中,尾节点的 next 指针指向头节点,头节点的 prev 指针指向尾节点。

这种差异导致了双向链表和双向循环链表在某些操作上的不同。例如,在双向链表中,我们不能直接访问尾节点的前一个节点,因为尾节点的 prev 指针指向 null。而在双向循环链表中,我们可以直接访问尾节点的前一个节点,因为尾节点的 prev 指针指向头节点。

双向链表和双向循环链表的实现方法

双向链表的实现方法

class Node {
public:
    int data;
    Node* next;
    Node* prev;

    Node(int data) {
        this->data = data;
        this->next = nullptr;
        this->prev = nullptr;
    }
};

class DoublyLinkedList {
public:
    Node* head;
    Node* tail;

    DoublyLinkedList() {
        this->head = nullptr;
        this->tail = nullptr;
    }

    void add(int data) {
        Node* new_node = new Node(data);
        if (this->head == nullptr) {
            this->head = new_node;
            this->tail = new_node;
        } else {
            this->tail->next = new_node;
            new_node->prev = this->tail;
            this->tail = new_node;
        }
    }

    void remove(int data) {
        Node* current = this->head;
        while (current != nullptr) {
            if (current->data == data) {
                if (current == this->head) {
                    this->head = current->next;
                    if (this->head != nullptr) {
                        this->head->prev = nullptr;
                    }
                } else if (current == this->tail) {
                    this->tail = current->prev;
                    if (this->tail != nullptr) {
                        this->tail->next = nullptr;
                    }
                } else {
                    current->prev->next = current->next;
                    current->next->prev = current->prev;
                }
                delete current;
                return;
            }
            current = current->next;
        }
    }

    int search(int data) {
        Node* current = this->head;
        int index = 0;
        while (current != nullptr) {
            if (current->data == data) {
                return index;
            }
            index++;
            current = current->next;
        }
        return -1;
    }

    void print() {
        Node* current = this->head;
        while (current != nullptr) {
            std::cout << current->data << " ";
            current = current->next;
        }
        std::cout << std::endl;
    }
};

双向循环链表的实现方法

class Node {
public:
    int data;
    Node* next;
    Node* prev;

    Node(int data) {
        this->data = data;
        this->next = nullptr;
        this->prev = nullptr;
    }
};

class DoublyCircularLinkedList {
public:
    Node* head;
    Node* tail;

    DoublyCircularLinkedList() {
        this->head = nullptr;
        this->tail = nullptr;
    }

    void add(int data) {
        Node* new_node = new Node(data);
        if (this->head == nullptr) {
            this->head = new_node;
            this->tail = new_node;
            new_node->next = new_node;
            new_node->prev = new_node;
        } else {
            new_node->next = this->head;
            new_node->prev = this->tail;
            this->head->prev = new_node;
            this->tail->next = new_node;
            this->tail = new_node;
        }
    }

    void remove(int data) {
        Node* current = this->head;
        while (current != nullptr) {
            if (current->data == data) {
                if (current == this->head) {
                    this->head = current->next;
                    this->tail->next = this->head;
                    this->head->prev = this->tail;
                } else if (current == this->tail) {
                    this->tail = current->prev;
                    this->tail->next = this->head;
                    this->head->prev = this->tail;
                } else {
                    current->prev->next = current->next;
                    current->next->prev = current->prev;
                }
                delete current;
                return;
            }
            current = current->next;
        }
    }

    int search(int data) {
        Node* current = this->head;
        int index = 0;
        while (current != nullptr) {
            if (current->data == data) {
                return index;
            }
            index++;
            current = current->next;
            if (current == this->head) {
                break;
            }
        }
        return -1;
    }

    void print() {
        Node* current = this->head;
        while (current != nullptr) {
            std::cout << current->data << " ";
            current = current->next;
            if (current == this->head) {
                break;
            }
        }
        std::cout << std::endl;
    }
};

双向链表和双向循环链表的应用场景

双向链表和双向循环链表被广泛应用于各种算法和应用程序中。以下是其中一些应用场景:

双向链表的应用场景

  • 栈: 栈是一种后进先出(LIFO)的数据结构。我们可以用双向链表来实现栈。在双向链表中,我们可以把栈顶元素放在链表的头结点,把栈底元素放在链表的尾结点。这样,我们就