我有一个用于交换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);
}
大约在排序的一半时,它将节点的下一个指针之一设置为NULL,然后在我打印列表时,将其正确排序为该值,但是由于指针被错误地设置为NULL,因此其余部分丢失了。
我检查并:
我的初始列表是正确的,并且没有错误连接的节点。
仅使用非空有效节点调用我的交换函数。
所以我责怪交换功能。这有什么问题吗?
最佳答案
我认为当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个指针需要更新。
我建议坐着铅笔和纸坐下来,首先确定需要更新的指针,然后确定每个指针的最终值是什么。知道这一点,编码部分应该很容易。