C++ 为什么它只打印双链表的第一个值,而我的程序却崩溃了
我试图创建一个双链接列表,然后打印它的值,但是输出只显示第一个值,然后整个程序就崩溃了 我不明白代码中的问题在哪里 输入 三, 1 2 3 预期产量 1 2 3 电流输出 一, 在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址 没什么,我听见你说了?嗯,这将是一个问题:- 更详细地说,行:C++ 为什么它只打印双链表的第一个值,而我的程序却崩溃了,c++,doubly-linked-list,C++,Doubly Linked List,我试图创建一个双链接列表,然后打印它的值,但是输出只显示第一个值,然后整个程序就崩溃了 我不明白代码中的问题在哪里 输入 三, 1 2 3 预期产量 1 2 3 电流输出 一, 在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址 没什么,我听见你说了?嗯,这将是一个问题:- 更详细地说,行: node *temp; 将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改: temp->next = ne
node *temp;
将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改:
temp->next = newnode;
换句话说,如果幸运的话,它很可能会使用无效的指针值并崩溃。如果你运气不好,它不会崩溃,而是会在之后的某个时候表现出一些奇怪的行为
如果您不担心列表中的顺序,可以通过始终在标题处插入以下内容来解决此问题:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
} else {
newnode->next = head->next;
newnode->prev = 0;
}
head = newnode;
return head;
}
如果您关心订单,则必须根据该值找出新节点的位置,例如:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
// Special case for empty list, just make new list.
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
head = newnode;
return head;
}
// Special case for insertion before head.
if (head->data > val) {
newnode->next = head->next;
newnode->prev = 0;
head = newnode;
return head;
}
// Otherwise find node you can insert after, and act on it.
// Checknode will end up as first node where next is greater than
// or equal to insertion value, or the last node if it's greater
// than all current items.
node *checknode = head;
while (checknode->next != 0 && (checknode->next->data < val) {
checknode = checknode->next;
}
// Then it's just a matter of adjusting three or four pointers
// to insert (three if inserting after current last element).
newnode->next = checknode->next;
newnode->prev = checknode;
if (checknode->next != 0) {
checknode->next->prev = newnode;
}
checknode->next = newnode;
return head;
}
在上面标记为1和2的行之间,究竟是什么将变量temp设置为指向实际节点,而不是指向某个任意内存地址
没什么,我听见你说了?嗯,这将是一个问题:-
更详细地说,行:
node *temp;
将temp设置为指向某个随机位置,除非您的列表当前为空,否则在您尝试执行之前,不会有任何更改:
temp->next = newnode;
换句话说,如果幸运的话,它很可能会使用无效的指针值并崩溃。如果你运气不好,它不会崩溃,而是会在之后的某个时候表现出一些奇怪的行为
如果您不担心列表中的顺序,可以通过始终在标题处插入以下内容来解决此问题:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
} else {
newnode->next = head->next;
newnode->prev = 0;
}
head = newnode;
return head;
}
如果您关心订单,则必须根据该值找出新节点的位置,例如:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
// Special case for empty list, just make new list.
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
head = newnode;
return head;
}
// Special case for insertion before head.
if (head->data > val) {
newnode->next = head->next;
newnode->prev = 0;
head = newnode;
return head;
}
// Otherwise find node you can insert after, and act on it.
// Checknode will end up as first node where next is greater than
// or equal to insertion value, or the last node if it's greater
// than all current items.
node *checknode = head;
while (checknode->next != 0 && (checknode->next->data < val) {
checknode = checknode->next;
}
// Then it's just a matter of adjusting three or four pointers
// to insert (three if inserting after current last element).
newnode->next = checknode->next;
newnode->prev = checknode;
if (checknode->next != 0) {
checknode->next->prev = newnode;
}
checknode->next = newnode;
return head;
}
实际上,您并没有将任何内容链接在一起。此行:ifhead==0 temp=head=newnode;这是链接列表包含值的唯一原因。第一个值将head设置为它的值,当您打印head时,您将获得该值。为了正确地创建链表,您需要一个头和尾指针。头部指向列表中的第一个元素,尾部指向最后一个元素。将元素添加到列表末尾时,使用tail查找最后一个元素并链接到该元素。使链表成为一个可以封装头和尾的类是最容易的:
struct Node {
public:
int data;
node *next;
node *prev;
Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};
class LinkedList {
private:
Node* head;
Node* tail;
public:
LinkedList() { head = tail = nullptr; }
// This function adds a node to the end of the linked list
void add(int data) {
Node* newNode = new Node(data);
if (head == nullptr) { // the list is empty
head = newNode;
tail = newNode;
}
else { // the list is not empty
tail->next = newNode; // point the last element to the new node
newNode->prev = tail; // point the new element to the prev
tail = tail->next; // point the tail to the new node
}
}
};
int main() {
LinkedList lList;
lList.add(1);
lList.add(2);
// etc...
return 0;
}
实际上,您并没有将任何内容链接在一起。此行:ifhead==0 temp=head=newnode;这是链接列表包含值的唯一原因。第一个值将head设置为它的值,当您打印head时,您将获得该值。为了正确地创建链表,您需要一个头和尾指针。头部指向列表中的第一个元素,尾部指向最后一个元素。将元素添加到列表末尾时,使用tail查找最后一个元素并链接到该元素。使链表成为一个可以封装头和尾的类是最容易的:
struct Node {
public:
int data;
node *next;
node *prev;
Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};
class LinkedList {
private:
Node* head;
Node* tail;
public:
LinkedList() { head = tail = nullptr; }
// This function adds a node to the end of the linked list
void add(int data) {
Node* newNode = new Node(data);
if (head == nullptr) { // the list is empty
head = newNode;
tail = newNode;
}
else { // the list is not empty
tail->next = newNode; // point the last element to the new node
newNode->prev = tail; // point the new element to the prev
tail = tail->next; // point the tail to the new node
}
}
};
int main() {
LinkedList lList;
lList.add(1);
lList.add(2);
// etc...
return 0;
}
我不明白你想说什么@paxdiablo@BATMAN_X您的else case通过写入temp->来解除temp的引用,但temp只是声明的,从未使用地址初始化过,因此它有一个未定义的值,因此您的程序有未定义的行为,在本例中会崩溃。您需要先将某个节点的有效内存地址分配给temp,然后才能取消引用。@BATMAN_X,我已经调整了该部分,希望能让它更清晰。我不明白您想说什么@paxdiablo@BATMAN_X您的else案例通过写入temp->来解除temp的引用,但temp只是声明的,从未使用地址初始化,所以它有一个未定义的值,所以你的程序有未定义的行为,在这种情况下会崩溃。您需要将某个节点的一些有效内存地址分配给temp,然后才能取消引用它。@BATMAN_X,我已经调整了该部分,希望能让它更清晰。