【发布时间】:2016-07-05 06:39:49
【问题描述】:
我正在尝试创建已排序的链表 = 在创建时对其进行排序。想法很简单,插入一个节点 - 并检查上一个是否更小,如果是,则检查上一个的上一个,依此类推,直到找到它的位置。我已经创建了这段代码。
struct Node{
Node *prev;
Node *next;
int value;
};
struct List{
Node *head = nullptr;
Node *tail = nullptr;
};
在这里我创建了一个节点和一个列表的“持有者” = 引用列表的第一项和最后一项。
void insertNode(Node *&head,Node *&tail, int value ){
Node *tmp = new Node;
tmp -> prev = nullptr;
tmp -> next = nullptr;
tmp -> value = value;
head = tmp;
tail = tmp;
}
此函数检查列表是否为空,如果是,则将节点插入头尾(例如头=尾=列表中只有一个节点);
困扰我的是插入节点的功能
void insertIt(Node *&head , Node *&tail , int value){
if( head == nullptr){
insertNode(head,tail,value);
}
else{
Node *tmp = new Node;
tmp -> value = value;
if( value < tail -> value){
while(value < tail -> prev -> value){
tail = tail -> prev;
if( tail -> prev == nullptr){
tmp -> next = head;
tmp -> prev = nullptr;
head -> prev = tmp;
head = tmp;
return;
}
}
tail -> prev -> next = tmp;
tmp -> prev = tail -> prev;
tmp -> next = tail;
tail -> prev = tmp;
}else{
tmp -> next = nullptr;
tmp ->prev = tail;
tail -> next = tmp;
tail = tmp;
}
}
}
如果列表为空,则调用insertNode(),如果节点的值小于前一个节点的值,则爬取列表以找到它的位置。
只有当插入的第一个节点也是最小的节点时,这段代码才有效。例如
insertIt(list.head , list.tail , -1);
insertIt(list.head , list.tail , 0);
insertIt(list.head , list.tail , 7);
insertIt(list.head , list.tail , 1);
insertIt(list.head , list.tail , 2);
insertIt(list head , list.tail , 2);
有效,如果我打印列表,它的排序很好。但是
insertIt(list.head , list.tail , -2);
insertIt(list.head , list.tail , -1);
insertIt(list.head , list.tail , 7);
insertIt(list.head , list.tail , 1);
insertIt(list.head , list.tail , 2);
insertIt(list.head , list.tail , 2);
第一个节点不是最小的节点,它会使程序崩溃。我以为是我将一个值与 nullptr 进行比较,所以我添加了您可以在 insertIt() 函数中看到的一段代码,那就是
if( tail -> prev == nullptr){
tmp -> next = head;
tmp -> prev = nullptr;
head -> prev = tmp;
head = tmp;
return;
}
这会检查节点是否为头,并与新节点交换头,使新节点成为新头。
为什么会导致代码崩溃?我没能找到一个合理的答案。另外,我该如何改进我的“算法”以使其更有效?
【问题讨论】:
-
首先,您应该在调试器中运行以捕捉正在运行的崩溃并查看它在哪里以及所有相关变量的值是什么。如果没有帮助,则使用调试器逐行逐行执行代码,以查看它的作用以及所有变量如何变化。
-
"如果列表为空,则调用 insertNode(),如果节点的值小于前一个节点的值.." ??但是列表是空的..
-
我正在使用代码块,并且调试器指出,在我添加的代码行(我写的最后一个代码),我对 c/c++ 世界有点陌生,没有使用过那么多调试器,我猜代码块调试器不是最好的。你能推荐一些好的吗?
-
我可以看到的是,在
insertIt中,您在寻找插入新节点的正确位置时重置了tail,从而破坏了指向链表中最后一个节点的指针。正确的方法是使用您初始化到尾部的另一个指针并将其用于搜索。无论如何,您使用tail->prev->value取消引用tail->prev而不检查tail->prev != nullptr。 -
当您发布代码时,请尝试确保您的缩进是一致且可读的,并且您没有过多的空格。另请注意:C != C++ 和 "c/c++" 是 C 和/或 C++ 的简写,尤其是当 one 仅表示其中之一时。
标签: c++ algorithm sorting linked-list