如何在C++中合并已排序的列表

How to merge sorted lists in C++?

本文关键字:排序 列表 合并 C++      更新时间:2023-10-16

我知道这个问题已经被问了很多次,部分答案是关于合并排序的问题,但我似乎不太明白。

这是我的代码:

#include <iostream>
using namespace std;
struct listNode {
    int info;
    struct listNode *next;
};

struct listNode * addHead(struct listNode* head, int k);
void printAll(struct listNode *head);
struct listNode * deleteLast(struct listNode *head);
struct listNode * append(struct listNode *a, struct listNode *b);
struct listNode * zip(struct listNode *a, struct listNode *b);
struct listNode * merge(struct listNode *a, struct listNode*b);
int main() 
{
    listNode *list1 = 0;
    listNode *list2 = 0;
    listNode *list3 = 0;
    listNode *list4 = 0;
    listNode *list5 = 0;
    //fill list1
    list1 = addHead(list1, 6);
    list1 = addHead(list1, 4);
    list1 = addHead(list1, 2);
    //fill list2
    list2 = addHead(list2, 3);
    list2 = addHead(list2, 1);

    //test deleteLast
    cout << "List 1 contains: " << endl;
    printAll(list1);
    cout << "Deleting last node of List 1. Now contains: " << endl;
    list1 = deleteLast(list1);
    printAll(list1);
    cout << "List 2 contains: " << endl;
    printAll(list2);
    //test append
    cout << "Appending list 1 and list 2 yields: " << endl;
    list3 = append(list1, list2);
    printAll(list3);
    //zip test
    cout << "The zipped list of list 1 and list 2 is: " << endl;
    list4 = zip(list1, list2);
    printAll(list4);
    //merge test
    cout << "The merged list of list1 and list 2 is: " << endl;
    list5 = merge(list1, list2);
    printAll(list5);
    return 0;
}
struct listNode *deleteLast(struct listNode *head) {
    if (head == 0) {
        return NULL;
    } else if (head->next == 0) {
        delete head;
        return NULL;
    } else {
        head->next = deleteLast(head->next);
    }
    return head;
}
struct listNode * addHead(struct listNode *head, int k) {
    listNode *nnode = new listNode;
    nnode->info = k;
    nnode->next = head;
    return nnode;
}
void printAll(listNode *head) {
    if (head == 0) {
        cout << endl;
    } else {
        cout << head->info << "->";
        printAll(head->next);
    }
}
struct listNode * append(struct listNode *ahead,struct listNode *bhead) {
    if (bhead == 0) {
        return ahead;
    } else if (ahead == 0) {
        return bhead;
    } else {
        ahead->next = append(ahead->next, bhead);
    }
    return ahead;
}
struct listNode * zip(struct listNode *a, struct listNode *b) 
{
    if (b == 0) {
        return 0;
    } else {
        listNode *tmp = a->next;
        a->next = b;
        a->next = zip(b, tmp);
    }
    return a;
}
struct listNode *merge(struct listNode *a, struct listNode *b)
{
    listNode *result = NULL;
    if (a == NULL)
        return b;
    else if (b == NULL)
        return a;
    if (a->info < b->info) {
        result = a;
        result->next = merge(a->next, b);
    } else {
        result = b;
        result -> next = merge(a, b->next);
    }
    return result;
}

现在它就是不能正常工作。我陷入了一个无限循环,然后出现了分段错误。有人能告诉我我做错了什么吗?

我会给你一个提示。尝试删除代码中看似正常的部分,即append和zip函数。只需在它们周围放置一个注释块,然后重新运行程序。您将看到它按预期工作。

这里的问题是如何实现这些功能。在所有情况下,您都将指针传递给listNode,而不是副本或其他任何东西。在这种情况下,您对传递的指针所指向的对象所做的所有更改都将反映在未来对任何其他函数的调用中。因此,当您创建list3和list4时,您正在积极修改当前存在的list1和list2。它们不是独立的列表,它们都是使用指针语义创建的。

因此,list2的第一个元素指向list1。如果您想查看证明,请在执行zip()append()之后,在list1和list2上使用printAll()

指针可能会导致许多看起来非常不寻常的问题,但只要您意识到指针是而不是对象本身,而是一个碰巧存储对象地址的单独值,您就可以看到对指向的对象进行修改会如何导致函数外的状态更改。