【问题标题】:How can one implement a doubly-linked list reverse element access (for when the element is very close to the end)如何实现双向链表反向元素访问(当元素非常接近末尾时)
【发布时间】:2022-12-10 21:26:47
【问题描述】:

我正在尝试在 C++ 中实现一个双向链表。我正在处理的成员函数之一是访问元素,它将返回一个节点指针。 我最初的实现是完全正常的,但我意识到有些情况下效率很低。例如,如果此列表中有 100 万个节点,那么访问第 999,999 个节点将比仅从“最后一个”指针节点向后访问慢得多。 不幸的是,我对这种反向访问的实现不起作用。我检查了for循环范围,肯定是正确的。

这是相关的代码部分:

    Node * getNode(int element) {
        if (element + 1 > listsize / 2) {
            Node * node = last;
            for (int i = 0; i < listsize - element - 1; i++)
                node = node -> previousnode;
            return node;
        }
        Node * node = head;
        for (int i = 0; i < element; i++)
            node = node -> nextnode;
        return node;
    }

我的整个程序可以在这里找到,以防有人想澄清对范围、声明等的担忧:

#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node * nextnode;
    Node * previousnode;
};

class DoublyLinkedList {
public:
    Node * head = new Node;
    Node * last = head;
    int listsize = 0;
    DoublyLinkedList(int size) {
        Node * previous = nullptr;
        Node * current = nullptr;
        previous = head;
        for (int i = 1; i < size; i++) {
            current = new Node;
            previous -> nextnode = current;
            current -> previousnode = previous;
            previous = current;
            last = current;
        }
        listsize = size;
        head -> previousnode = nullptr;
        last -> nextnode = nullptr;
    }
    DoublyLinkedList(int size, int fill) {
        Node * previous = nullptr;
        Node * current = nullptr;
        previous = head;
        head -> data = fill;
        for (int i = 1; i < size; i++) {
            current = new Node;
            previous -> nextnode = current;
            current -> previousnode = previous;
            current -> data = fill;
            previous = current;
            last = current;
        }
        listsize = size;
        head -> previousnode = nullptr;
        last -> nextnode = nullptr;
    }
    Node * getNode(int element) {
        if (element + 1 > listsize / 2) {
            Node * node = last;
            for (int i = 0; i < listsize - element - 1; i++)
                node = node -> previousnode;
            return node;
        }
        Node * node = head;
        for (int i = 0; i < element; i++)
            node = node -> nextnode;
        return node;
    }
    void editNode(int element, int value) {
        Node * node = getNode(element);
        node -> data = value;
        return;
    }
    void push_front(int value = 0) {
        Node * pushNode = new Node;
        pushNode -> nextnode = head;
        pushNode -> data = value;
        head -> previousnode = pushNode;
        head = pushNode;
        head -> previousnode = nullptr;
        listsize++;
    }
    void pop_front() {
        Node * newhead = head -> nextnode;
        delete head;
        head = newhead;
        head -> previousnode = nullptr;
        listsize--;
    }
    void push_back(int value = 0) {
        Node * pushNode = new Node;
        last -> nextnode = pushNode;
        last = pushNode;
        pushNode -> data = value;
        last -> nextnode = nullptr;
        listsize++;
    }
    void pop_back() {
        Node * newlast = last -> previousnode;
        delete last;
        last = newlast;
        last -> nextnode = nullptr;
        listsize--;
    }
    int size() {
        return listsize;
    }
    void displayList() {
        displayList(0, listsize);
    }
    void displayList(int start, int finish) {
        cout << "List: ";
        Node * a = getNode(start);
        cout << a -> data << " <=> ";
        for (int i = start + 1; i < finish - 1; i++) {
            a = a -> nextnode;
            cout << a -> data << " <=> ";
        }
        a = a -> nextnode;
        cout << a -> data;
        cout << "\n\n";
    }
};

int main(int argc, const char * argv[]) {
    DoublyLinkedList testlist(5, 3);
    

    testlist.push_front(8);
    testlist.push_back(10);
    testlist.displayList();
    cout << testlist.last -> data << "a\n";
    Node * testnode = testlist.last;
    cout << testnode -> data << "b\n";
    testnode = testnode -> previousnode;
    cout << testnode -> data << "c\n";

    
    /*testlist.editNode(1, 22);
    Node * testnode = testlist.getNode(2);
    testnode = testnode -> previousnode;
    cout << testnode -> data << endl;*/

    /*
    int inputc;
    string operation;
    int number;
    cin >> inputc;
    cout << "Initial ";
    testlist.displayList();
    while (inputc--) {
        cin >> operation;
        if (operation == "pushback") {
            cin >> number;
            testlist.push_back(number);
        } else if (operation == "popback")
            testlist.pop_back();
        else if (operation == "pushfront") {
            cin >> number;
            testlist.push_front(number);
        } else if (operation == "popfront")
            testlist.pop_front();
        else if (operation == "access") {
            cin >> number;
            Node * n = testlist.getNode(number);
            cout << "Node stores value: " << n -> data << "\n";
        } else if (operation == "size") {
            int a = testlist.size();
            cout << "Size: " << a << "\n";
        } else if (operation == "edit") {
            cin >> number;
            int edit;
            cin >> edit;
            testlist.editNode(number, edit);
        } else if (operation == "partialdisplay") {
            int start, end;
            cin >> start >> end;
            testlist.displayList(start, end);
        }
        testlist.displayList();
    }
    */
}


我已经测试了“previousnode”指针,以及所有的 push 和 pop 函数。您可以看到我进行的一些测试,在 main() 函数中将其注释为多行 cmets。

【问题讨论】:

  • 无论你在哪里学会做#include &lt;bits/stdc++.h&gt; using namespace std;请尽快忘记,并将源放入最近的垃圾箱。
  • 至于你的问题,除非列表是有序的,或者你有其他方法来推断节点的(近似)位置,否则你无法判断你是否应该从头或尾开始寻找它。您真正能做的就是从一开始就进行线性搜索。

标签: c++ pointers nodes doubly-linked-list


【解决方案1】:

你的push_front有7行代码,而push_back只有6行。

附言: 按索引/位置访问元素以某种方式违背了使用双链表的目的(通常)。

【讨论】:

    猜你喜欢
    • 2020-07-11
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    相关资源
    最近更新 更多