C++ 为什么在排序链表上执行merge时总是将两个列表都设置为NULL,而只有一个列表应该设置为NULL?

C++ 为什么在排序链表上执行merge时总是将两个列表都设置为NULL,而只有一个列表应该设置为NULL?,c++,merge,linked-list,singly-linked-list,C++,Merge,Linked List,Singly Linked List,老实说,我已经做了大约10个小时了,尝试了一种又一种方法来让它发挥作用。我试图创建第三个列表,即两个列表合并在一起并从低到高排序(无重复),然后将第一个列表设置为新列表,从而将第二个列表合并为第一个列表。但每当我运行程序时,我都会得到listData==NULL,即使在newListCurr绝对应该向newList添加元素的测试用例中也是如此。我一直很难理解链表,所以也许我误解了一些基本原理,但我一辈子也弄不明白这一点。该方法不需要声明单个新节点,并且只能具有O(n)的时间复杂度,这使得这变得更

老实说,我已经做了大约10个小时了,尝试了一种又一种方法来让它发挥作用。我试图创建第三个列表,即两个列表合并在一起并从低到高排序(无重复),然后将第一个列表设置为新列表,从而将第二个列表合并为第一个列表。但每当我运行程序时,我都会得到listData==NULL,即使在newListCurr绝对应该向newList添加元素的测试用例中也是如此。我一直很难理解链表,所以也许我误解了一些基本原理,但我一辈子也弄不明白这一点。该方法不需要声明单个新节点,并且只能具有O(n)的时间复杂度,这使得这变得更加困难。我尝试了几种方法,比如尝试将它们直接插入listData(第一个列表),但是curr指针存在一个一致的问题,实际上并不影响它们各自的listData

编辑:假定列表在合并之前已排序

这里是合并方法,其他一切都按预期工作,只有合并方法出错

template <class ItemType>
void SortedList<ItemType>::merge(SortedList& list) {
    Node<ItemType> * curr1 = listData;
    Node<ItemType> * curr2 = list.listData;
    Node<ItemType> * newList = NULL;
    Node<ItemType> * newListCurr = newList;
    while(curr2 != NULL || curr1 != NULL) {
        if(curr2 == NULL) {
            newListCurr = curr1;
            curr1 = curr1->next;
            newListCurr = newListCurr->next;
        }
        else if(curr1 == NULL) {
            newListCurr = curr2;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
        else if(curr1->info < curr2->info) {
            newListCurr = curr1;
            curr1 = curr1->next;
            newListCurr = newListCurr->next;
        } else if (curr2->info < curr1->info) {
            newListCurr = curr2;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
        else if (curr1->info == curr2->info) {
            newListCurr = curr1;
            curr1 = curr1->next;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
    }
    list.listData = NULL;
    listData = newList;
}
模板
无效分类列表::合并(分类列表和列表){
节点*curr1=listData;
节点*curr2=list.listData;
Node*newList=NULL;
节点*newListCurr=newList;
while(curr2!=NULL | | curr1!=NULL){
如果(curr2==NULL){
newListCurr=curr1;
curr1=curr1->next;
newListCurr=newListCurr->next;
}
else if(curr1==NULL){
newListCurr=curr2;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
否则如果(curr1->infoinfo){
newListCurr=curr1;
curr1=curr1->next;
newListCurr=newListCurr->next;
}否则如果(curr2->infoinfo){
newListCurr=curr2;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
否则如果(curr1->info==curr2->info){
newListCurr=curr1;
curr1=curr1->next;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
}
list.listData=NULL;
listData=newList;
}
编辑:我为那些可能有同样问题的人找到了一个解决方案。我需要将newList和newListCurr设置为一个节点,然后才能使用newListCurr修改newList的其余部分。这是我的更新代码:

template <class ItemType>
void SortedList<ItemType>::merge(SortedList& list) {
    Node<ItemType> * curr1 = listData;
    Node<ItemType> * curr2 = list.listData;
    Node<ItemType> * newList = NULL;
    Node<ItemType> * newListCurr = newList;
    if(curr2 != NULL || curr1!= NULL) {
        if(curr2 == NULL) {
            newListCurr = curr1;
            curr1 = curr1->next;
        } else if(curr1 == NULL) {
            newListCurr = curr2;
            curr2 = curr2->next;
        } else if(curr1->info < curr2->info) {
            newListCurr = curr1;
            curr1 = curr1->next;
        } else if (curr2->info < curr1->info) {
            newListCurr = curr2;
            curr2 = curr2->next;
        } else if (curr1->info == curr2->info) {
            newListCurr = curr1;
            curr1 = curr1->next;
            curr2 = curr2->next;
        }
        newList = newListCurr;
    }
    while(curr2 != NULL || curr1 != NULL) {
        if(curr2 == NULL) {
            newListCurr->next = curr1;
            curr1 = curr1->next;
            newListCurr = newListCurr->next;
        }
        else if(curr1 == NULL) {
            newListCurr->next = curr2;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
        else if(curr1->info < curr2->info) {

            newListCurr->next = curr1;
            curr1 = curr1->next;
            newListCurr = newListCurr->next;
        } else if (curr2->info < curr1->info) {
            newListCurr->next = curr2;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
        else if (curr1->info == curr2->info) {
            newListCurr->next = curr1;
            curr1 = curr1->next;
            curr2 = curr2->next;
            newListCurr = newListCurr->next;
        }
    }
    list.listData = NULL;
    listData = newList;
}
模板
无效分类列表::合并(分类列表和列表){
节点*curr1=listData;
节点*curr2=list.listData;
Node*newList=NULL;
节点*newListCurr=newList;
如果(curr2!=NULL | | curr1!=NULL){
如果(curr2==NULL){
newListCurr=curr1;
curr1=curr1->next;
}else if(curr1==NULL){
newListCurr=curr2;
curr2=curr2->next;
}否则如果(curr1->infoinfo){
newListCurr=curr1;
curr1=curr1->next;
}否则如果(curr2->infoinfo){
newListCurr=curr2;
curr2=curr2->next;
}否则如果(curr1->info==curr2->info){
newListCurr=curr1;
curr1=curr1->next;
curr2=curr2->next;
}
newList=newListCurr;
}
while(curr2!=NULL | | curr1!=NULL){
如果(curr2==NULL){
newListCurr->next=curr1;
curr1=curr1->next;
newListCurr=newListCurr->next;
}
else if(curr1==NULL){
newListCurr->next=curr2;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
否则如果(curr1->infoinfo){
newListCurr->next=curr1;
curr1=curr1->next;
newListCurr=newListCurr->next;
}否则如果(curr2->infoinfo){
newListCurr->next=curr2;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
否则如果(curr1->info==curr2->info){
newListCurr->next=curr1;
curr1=curr1->next;
curr2=curr2->next;
newListCurr=newListCurr->next;
}
}
list.listData=NULL;
listData=newList;
}

newList
在顶部被设置为NULL,并且永远不会重新分配。当您设置
self时。listData=newList最后,newList仍然为空


也许您认为,如果您将
newlistcur
设置为某个值,它会设置
newList
——它不会。它们是独立的指针。

在原始函数代码中有两个问题。第一个是指针
newList
在函数中未被更改且始终等于NULL

Node<ItemType> * newList = NULL;
第二个问题是,您总是更改指针
newListCurr
,而不是指针
newListCurr->next
的当前值,例如在这个if语句中

    if(curr2 == NULL) {
        newListCurr = curr1;
        ^^^^^^^^^^^^^^^^^^^^ 
        curr1 = curr1->next;
        newListCurr = newListCurr->next;
    }
在新更新的函数实现中,您可以避免这个错误,因为现在您确实正在更改当前指针的数据成员
next

    if(curr2 == NULL) {
        newListCurr->next = curr1;
        ^^^^^^^^^^^^^^^^^^^^^^^^^
        curr1 = curr1->next;
        newListCurr = newListCurr->next;
然而,函数的新实现过于复杂,因为相同的代码实际上在第一个if语句中重复

如果使用指向指针的指针,则该函数可以更简单地实现。我不知道你的类是如何定义的,所以我定义了一个简单的类

该函数可以插入重复项,但您可以使用附加的if语句来更改它,该语句表示未插入重复项

这是一个演示程序

#include <iostream>

template <class ItemType>
class SortedList
{
private:
    struct Node
    {
        ItemType info;
        Node *next;
    } *listData = nullptr;

public:
    void insert( const ItemType &info )
    {
        Node **tail = &listData;

        while ( *tail ) tail = &( *tail )->next;

        *tail = new Node { info, nullptr };
    }

    void merge( SortedList<ItemType> & list )
    {
        Node *newListData = nullptr;

        Node **current = &newListData;
        Node **first   = &listData;
        Node **second  = &list.listData;

        while ( *first && *second )
        {
            if ( ( *second )->info < ( *first )->info )
            {
                *current = *second;
                *second = ( *second )->next;
                current =  &( *current )->next;
            }
            else
            {
                *current = *first;
                *first = ( *first )->next;
                current =  &( *current )->next;
            }
        }

        while ( *first )
        {
            *current = *first;
            *first = ( *first )->next;
            current =  &( *current )->next;
        }

        while ( *second )
        {
            *current = *second;
            *second = ( *second )->next;
            current =  &( *current )->next;
        }

        listData = newListData;
    }

    friend std::ostream & operator <<( std::ostream &os, const SortedList<ItemType> &list )
    {
        for ( const SortedList<ItemType>::Node *current = list.listData; current; current = current->next )
        {
            os << current->info << " -> ";
        }

        return os << "null";
    }
};

int main() 
{
    SortedList<int> list1;
    SortedList<int> list2;

    const int N = 10;

    for ( int i = 0; i < N; i++ )
    {
        if ( i % 2 == 0 ) list1.insert( i );
        else list2.insert( i );
    }

    std::cout << list1 << '\n';
    std::cout << list2 << '\n';

    list1.merge( list2 );

    std::cout << list1 << '\n';
    std::cout << list2 << '\n';

    return 0;
}

我看到
节点*newList=NULL,没有任何更改,然后
listData=newList。为什么你期望
newList
不是
NULL
?通常人们想回答问题时会从问题中提取代码,p
#include <iostream>

template <class ItemType>
class SortedList
{
private:
    struct Node
    {
        ItemType info;
        Node *next;
    } *listData = nullptr;

public:
    void insert( const ItemType &info )
    {
        Node **tail = &listData;

        while ( *tail ) tail = &( *tail )->next;

        *tail = new Node { info, nullptr };
    }

    void merge( SortedList<ItemType> & list )
    {
        Node *newListData = nullptr;

        Node **current = &newListData;
        Node **first   = &listData;
        Node **second  = &list.listData;

        while ( *first && *second )
        {
            if ( ( *second )->info < ( *first )->info )
            {
                *current = *second;
                *second = ( *second )->next;
                current =  &( *current )->next;
            }
            else
            {
                *current = *first;
                *first = ( *first )->next;
                current =  &( *current )->next;
            }
        }

        while ( *first )
        {
            *current = *first;
            *first = ( *first )->next;
            current =  &( *current )->next;
        }

        while ( *second )
        {
            *current = *second;
            *second = ( *second )->next;
            current =  &( *current )->next;
        }

        listData = newListData;
    }

    friend std::ostream & operator <<( std::ostream &os, const SortedList<ItemType> &list )
    {
        for ( const SortedList<ItemType>::Node *current = list.listData; current; current = current->next )
        {
            os << current->info << " -> ";
        }

        return os << "null";
    }
};

int main() 
{
    SortedList<int> list1;
    SortedList<int> list2;

    const int N = 10;

    for ( int i = 0; i < N; i++ )
    {
        if ( i % 2 == 0 ) list1.insert( i );
        else list2.insert( i );
    }

    std::cout << list1 << '\n';
    std::cout << list2 << '\n';

    list1.merge( list2 );

    std::cout << list1 << '\n';
    std::cout << list2 << '\n';

    return 0;
}
0 -> 2 -> 4 -> 6 -> 8 -> null
1 -> 3 -> 5 -> 7 -> 9 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
null