我有一个用于交换2个节点的函数:
void swap(Node<T>* a, Node<T>* b) {
if(a->m_prev)
a->m_prev->m_next = b;
if(b->m_prev)
b->m_prev->m_next = a;
if(a->m_next)
a->m_next->m_prev = b;
if(b->m_next)
b->m_next->m_prev = a;
Node<T>* temp;
temp = a->m_prev;
a->m_prev = b->m_prev;
b->m_prev = temp;
temp = a->m_next;
a->m_next = b->m_next;
b->m_next = temp;
}
但是当与递归选择排序一起使用时:
void selectionSort(Node<T>* head) {
if(next(head) == NULL) {
return;
}
Node<T>* minimum = min(head);
swap(head,minimum);
selectionSort(minimum->m_next);
}
大约在排序的一半,它设置了我的一个节点&#39;下一个指针指向NULL,然后当我打印我的列表时,它正确地排序到该值,但其余部分丢失,因为指针被错误地设置为NULL。
我查了一下:
我的初始列表是正确的,没有错误连接的节点。
仅使用非空有效节点调用我的交换函数。
所以我责怪交换功能。它有什么问题吗?
答案 0 :(得分:2)
我认为当a
与列表中的b
相邻时会出现问题。例如,如果b->prev
指向a
(意味着a
就在列表中的b
之前)那么该行
b->prev->next = a;
相当于
a->next = a;
显然不是你想要的。
以下是有关如何解决双向链表中交换节点问题的一些提示。要交换的节点A和B将被称为内部节点。列表中的其他节点是外部节点。 A和/或B附近的外部节点应指定为W,X,Y和Z.远离A和B的外部节点应用省略号指定。交换内部节点时,交换中将涉及2,3或4个外部节点,如下所示
case 1: widely separated (four external nodes) ... W A X ... Y B Z ...
case 2: separated by one (three external nodes) ... W A X B Z ...
case 3: adjacent (two external nodes, A first) ... W A B Z ...
case 4: adjacent (two external nodes, B first) ... W B A Z ...
应该可以使用一组代码处理前两种情况(在情况2中,X连接到A和B两者对交换实现没有影响)。如果B在A之前,则可以通过交换函数参数来处理最后两种情况,以便变量a
始终指向第一个节点,变量b
始终指向第二个节点。因此,这四个案例减少到两个案例,模仿为
cases 1&2: ... W A X ... Y B Z ...
cases 3&4: ... W A B Z ...
在情况1和2中,内部节点上有4个需要更新的指针,以及需要更新的外部节点上的4个指针。在案例3和4中,内部节点上有4个指针需要更新,但外部节点上只有2个指针需要更新。
我建议用铅笔和纸坐下来,先找出需要更新的指针,然后确定每个指针的最终值是什么。知道了,编码部分应该很容易。
答案 1 :(得分:0)
您只需交换节点中的值即可避免指针灾难
答案 2 :(得分:0)
这应该有用。
void swap(Node<T>* a, Node<T>* b) {
if ( a == b )
{
return;
}
Node<T*> oldANext = a->m_next;
Node<T*> oldAPrev = a->m_prev;
Node<T*> oldBNext = b->m_next;
Node<T*> oldBPrev = b->m_prev;
// Special case when b is the next of a.
if ( a->m_next == b )
{
a->m_next = oldBNext;
a->m_prev = b;
b->m_next = a;
b->m_prev = oldAPrev;
if ( oldAPrev )
oldAPrev->m_next = b;
if ( oldBNext )
oldBNext->m_prev = a;
}
// Special case when b is the prev of a.
else if ( a->m_prev == b )
{
a->m_prev = oldBPrev;
a->m_next = b;
b->m_prev = a;
b->m_next = oldANext;
if ( oldANext )
oldANext->m_prev = b;
if ( oldBPrev )
oldBPrev->m_next = a;
}
// When a and b are not related.
else
{
a->m_next = oldBNext;
a->m_prev = oldBPrev;
b->m_next = oldANext;
b->m_prev = oldAPrev;
if ( oldANext )
oldANext->m_prev = b;
if ( oldAPrev )
oldAPrev->m_next = b;
if ( oldBNext )
oldBNext->m_prev = a;
if ( oldBPrev )
oldBPrev->m_next = a;
}
}