我的双链表交换功能有什么问题吗?

时间:2014-03-13 02:57:57

标签: c++

我有一个用于交换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。

我查了一下:

我的初始列表是正确的,没有错误连接的节点。

仅使用非空有效节点调用我的交换函数。

所以我责怪交换功能。它有什么问题吗?

3 个答案:

答案 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;
    }
}