当前位置: 首页 > 知识库问答 >
问题:

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

呼延聪
2023-03-14

我有一个用于交换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,其余的指针将丢失。

我查了一下然后:

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

我的swap函数只在非null有效节点上调用

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

共有3个答案

万俟鸿波
2023-03-14

这应该行得通。

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;
    }
}
戚勇
2023-03-14

只需交换节点中的值,即可避免指针灾难

仇睿
2023-03-14

我认为问题发生在a在列表中与b相邻时。例如,如果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中

我建议用铅笔和纸坐下来,首先确定需要更新的指针,然后确定每个指针的最终值。知道了这一点,编码部分应该很简单。

 类似资料:
  • 我用C语言编写了交换代码,但我在学校编译器中没有获得完美的成绩。我认为遵循代码有问题。我用结构和指针制作了双向链表。节点定义为: 下面的代码是交换代码,我让每个函数因子表示“struct node*p”是从头到尾的完整列表,“int a和b”是列表的秩,“count1(p)”是对完整列表中的节点进行计数并返回节点数(不包括头和尾)的函数。 以下代码是我的完整代码: 这是我的全部密码。我想知道是否有

  • 我正在尝试交换双链接列表中的两个节点。下面是具有交换功能的程序部分。 当我运行这个程序时,在第一个和第二个节点的情况下,它崩溃了。而在任何其他节点的情况下,它提供无限循环输出。(例如:-2- 我知道还有一些关于节点交换的问题,但是我没有找到任何与我的问题相似的问题。请帮帮我...!! 提前谢谢。

  • 我试图交换链表中节点的位置,然后使用排序函数进行排序。这两个函数中的任何一个都有逻辑错误。当我运行这个程序时,它会无限循环。 更新代码

  • 我在Java中实现一个双链接列表时遇到了一个问题。特别是要交换2个以下节点(在我的例子中,一个节点包含一个政治候选人)。 假设下面的DLL: head- 作为输出,我没有从头到尾的正确DLL,但从头到尾都很好: 我已经写了几个版本的这个方法reverseTwoNode。我甚至尝试在节点内部交换数据,而不是交换节点,我也有同样的问题。你能帮我真是太好了,我花了这么多时间在这个简单的功能上,我看不出有

  • 在今天的一次采访中,我被问到了这个问题。 除了回答倒序和前后遍历外,面试官还不断强调其中的一些“基本点”。我放弃了,当然在面试后做了一些调查。在双链表中插入和删除似乎比单链表更有效。我不太清楚如何才能更有效地使用双链接列表,因为显然需要更改更多的引用。有人能解释背后的秘密吗?老实说,我做了相当多的研究,但未能理解我的主要问题是,仍然需要对双链接列表进行O(n)搜索。

  • 问题内容: 运行此代码时,我不断收到此错误: 错误:大小写类型的字符不同,并且整数不能匹配 您可能会认为这不会造成问题,因为我正在查询中创建新列。我还想指出的是,如果有帮助,我正在使用旧版本的PostgreSQL。 问题答案: