【问题标题】:How to merge sorted lists in C++?如何在 C++ 中合并排序列表?
【发布时间】:2014-10-14 02:27:59
【问题描述】:

我知道这个问题已经被问过多次,并部分回答了合并排序问题,但我似乎无法正确回答。

这是我的代码:

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

现在它只是不能正常工作。我陷入无限循环,然后发生分段错误。谁能告诉我我有什么问题?

【问题讨论】:

  • 这可能是学习使用调试器的好机会。
  • 请参阅stackoverflow.com/help/on-topic:寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误以及重现它所需的最短代码问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建最小、完整和可验证的示例。

标签: c++ merge mergesort


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2021-10-06
    • 2010-11-12
    • 2019-03-20
    • 2014-12-02
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多