【发布时间】: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 <bits/stdc++.h> using namespace std;请尽快忘记,并将源放入最近的垃圾箱。 -
至于你的问题,除非列表是有序的,或者你有其他方法来推断节点的(近似)位置,否则你无法判断你是否应该从头或尾开始寻找它。您真正能做的就是从一开始就进行线性搜索。
标签: c++ pointers nodes doubly-linked-list