c++ - 反转两个节点之间的链表

标签 c++ data-structures linked-list doubly-linked-list

我正在为 CS 类(class)做一些家庭作业,并且在一个函数上遇到了一些困难,该函数旨在反转两个给定节点之间的双向链表。我对自己做错了什么感到很困惑,我搜索了谷歌和 SO,但找不到任何可以帮助我的东西。

我有一个双向链表,我实际上是将此函数用作辅助函数,以在作为函数参数给出的两个节点之间反转它。

下面是模板的代码,注释让你知道我的思维过程

template <class T>
void List<T>::reverse( ListNode * & startPoint, ListNode * & endPoint )
{
    //make sure that none of the pointers are null and that the start and 
    //end points aren't the same
    if(startPoint == NULL || endPoint == NULL || startPoint == endPoint)
        return;
    //Make two nodes denoting everything happening before the
    //start and everything after the end
    ListNode *before = NULL;
    ListNode *after = NULL;
    if(startPoint->prev != NULL)
        before = startPoint->prev;
    if(endPoint->next != NULL)
        after = endPoint->next;
    ListNode *temp = startPoint;
    ListNode *temp2;
    //run a loop actually reversing the list. I have identified
    //that this is where the problem is happening (obviously)
    //for some reason the prev pointer for every node is being set to null
    //so if I had a linked list with 1 2 3 4 5
    //after running this it's just 5
    while(temp!=endPoint && temp!=NULL){
        temp2 = temp->next;
        if(temp->prev!=NULL);
            temp->next = temp->prev;
        if(temp2!=NULL)
            temp->prev = temp2;
        temp = temp2;

    }
    //switch around the end and start pointers
    endPoint = startPoint;
    startPoint = temp;
    //make sure it's integrated into the rest of the linked list
    if(before != NULL){
        before->next = startPoint;
        startPoint->prev = before;
    }
    if(after != NULL){
        after->prev = endPoint;
        endPoint->next = after;
    }
}

那么,有什么想法吗? 我已经了解问题发生的位置和原因,但我不明白为什么会发生以及如何解决。

此外,如果您认为我在做一些多余或不必要的事情,请随时告诉我,我有时会那样做。

编辑:这是一个包容性函数,因此如果您在链表 {1, 2, 3, 4, 5, 6} 上调用它,并且指针指向值为 2 和 5 的节点,则链表将是更改为 {1, 5, 4, 3, 2, 6}

最佳答案

问题出在子列表的末端。

你没有给出一个完整的例子(这会有所帮助),但假设我们从列表 {1, 2, 3, 4, 5} 开始,然后我们尝试 reverse(s, e),其中 se 是指向 2 和 4 的指针。(所以我们想要的结果是 {1, 4, 3, 2, 5}。)

这是我在 ASCII 艺术方面的技能失败的地方,但“下一个”和“上一个”指针看起来像这样:

1-->2-->3-->4-->5

1<--2<--3<--4<--5

当控制离开 while 循环时,它们看起来像这样:

1<->2<--3   4-->5
1   2-->3<->4<--5

这几乎是我们想要的,但是进程很快就停止了一个节点(4 没有被逆转)。在“集成到列表的其余部分”之后,它们看起来像这样:

  ________ ___
 /   /    \   \
1   2<--3  >4-->5
1   2-->3-->4   5
 \___\_____/___/

不是很清楚,但是如果你从列表的开头开始向前移动,它就是 {1, 4, 5},如果你从末尾向后移动它就是 {5, 2, 3, 4, 1}。您已经打破了双向链接条件,即如果 a.next 指向 b,则 b.prev 指向 a,反之亦然。

我的建议(除了用铅笔和纸画更多箭头之外)是从列表中删除子列表,反转它,然后将它拼接回去;试图就地扭转它是令人困惑的。

关于c++ - 反转两个节点之间的链表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28639985/

相关文章:

Python:分割从命令行读取的值的有效方法

c - 在链表中使用 malloc 的问题

c++ - 使用 NULL 参数实例化模板类

c# - 我应该在与 C# 交互时使用固定大小的数据类型吗

python - 如何找到给定斐波那契数的索引

dictionary - Clojure - 沿着路径行走

c# - 保留插入顺序的通用键/值对集合?

Java-从文件中读取大数对并用链表表示它们,得到每对的和与积

c - c语言如何保持链表的头部?

c++ - 根据非类型参数值推导出类型列表