【问题标题】:Is anything wrong with my doubly linked list swap function?我的双向链表交换功能有什么问题吗?
【发布时间】:2014-03-13 02:57:56
【问题描述】:

我有一个用于交换 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,然后当我打印我的列表时,它被正确排序为该值,但其余部分丢失,因为指针被错误地设置为空。

我检查并:

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

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

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

【问题讨论】:

    标签: c++


    【解决方案1】:

    我认为当a 与列表中的b 相邻时会出现问题。例如,如果b-&gt;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个指针需要更新。

    我建议坐下来拿着铅笔和纸,首先确定需要更新的指针,然后确定每个指针的最终值是什么。知道这一点,编码部分应该很容易。

    【讨论】:

    • 我能做些什么来解决这个问题?我不确定如何。
    • @Milo 我在回答中添加了一些额外的注释。
    【解决方案2】:

    你可以只交换节点中的值以避免指针灾难

    【讨论】:

    • 重要的是我不会使节点包含的内容或节点本身无效。
    【解决方案3】:

    这应该可行。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-11
      • 1970-01-01
      相关资源
      最近更新 更多