我的双链表交换函数有什么问题吗?
Is anything wrong with my doubly linked list swap function?
我有一个用于交换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;
}
然而,当使用我的递归选择sort:
void selectionSort(Node<T>* head) {
if(next(head) == NULL) {
return;
}
Node<T>* minimum = min(head);
swap(head,minimum);
selectionSort(minimum->m_next);
}
大约在排序的中途,它将我的一个节点的下一个指针设置为NULL,然后当我打印我的列表时,它被正确地排序到该值,但其余的丢失,因为指针被错误地设置为NULL。
我检查过了,
我的初始列表是正确的,没有错误连接的节点。
我的swap函数只在非空的有效节点上调用。
所以我责怪swap函数。有什么问题吗?
我认为当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个指针需要更新。
我建议坐下来用铅笔和纸,首先确定需要更新的指针,然后确定您希望每个指针的最终值是什么。知道了这一点,编码部分应该很容易。
您可以直接交换节点中的值以避免指针灾难
应该可以。
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;
}
}
相关文章:
- 警告处理为错误这里有什么问题
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 当我尝试添加 2 个大字符串时,我无法弄清楚出了什么问题
- 违反const正确性:我应该现实地期待什么问题
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 我的逻辑反转字符串中的元音有什么问题?
- 需要以下代码的帮助,下面的代码有什么问题
- 常量公共成员有什么问题?
- 以下代码中的函数模板有什么问题?
- 这个返回元素位置的基于循环的函数有什么问题?
- creat_list2功能有什么问题?
- 格式说明符C++有什么问题
- 任何人都可以告诉我我的 C++ 代码出了什么问题?
- 从 argv[1] 转换为字符 * 字符串后有什么问题?
- 我的堆栈和库存清单程序的结构有什么问题?
- 此工厂功能有什么问题?
- 以下 C++ 代码有什么问题?
- 数组为此合并排序函数提供了正确的输出,但向量给出了不正确的输出.出了什么问题?
- reinterpret_cast,只读访问,简单的可复制类型,会出什么问题?
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了