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

时间:2014-10-14 02:28:00

标签: c++ merge mergesort

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

这是我的代码:

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

现在它无法正常工作。我陷入无限循环然后发生分段错误。有人能告诉我我的错误吗?

1 个答案:

答案 0 :(得分:0)

我会给你一个提示。尝试删除代码中看似起作用的部分,追加和zip功能。只需在它们周围放置一个注释块,然后重新运行该程序。你会看到它按预期运作。

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

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

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