使用链接列表合并两个已排序的列表

时间:2015-12-24 04:56:39

标签: c

我正在合并两个按升序排序的排序列表。我使用两个函数来完成这个任务:

  1. 第一个是Node * MergedSort(Node * a,Node * b),它接受两个排序列表的头节点并将它们合并在一起。

  2. 还有一个实用程序函数void MoveNode(Node ** dest,Node ** source),它接受源链表的头节点并将其放在目标列表的顶部。并使源链表的头部指向其下一个元素。

  3. 以下是执行此任务的代码:

    typedef struct container{
           int data;
           struct container *next;
     } Node;
    
    void MoveNode(Node **dest, Node **source){
        Node *newNode = *source;
        //Now source points to its second node;
        *source = newNode->next;
        //Connecting newNode to dest.
        newNode->next = *dest;
        //Now destination head points  to newNode
        *dest = newNode;
        return;
    }
    
    Node *MergedSort(Node *a, Node *b){
        Node dummy;
        Node *tail = &dummy;
        dummy.next = NULL;
    
        while(1){
                if (a == NULL){
                        tail->next = b;
                        break;
                }
                else if (b == NULL){
                        tail->next = a;
                        break;
                }
                else if (a->data < b->data){
                        MoveNode(&(tail->next), &a);
                }
                else{
                        MoveNode(&(tail->next), &b);
                }
                tail = tail->next;
        }
        return (dummy.next);
    }
    

    现在的问题是,如果我在这段代码中进行一些小改动,即将dummy定义为指向Node的指针,它会给我分段错误。这是错误的代码,只有一点变化,虚拟的声明现在是Node * dummy:

    void MoveNode(Node **dest, Node **source){
        Node *newNode = *source;
        //Now source points to its second node;
        *source = newNode->next;
        //Connecting newNode to dest.
        newNode->next = *dest;
        //Now destination head points  to newNode
        *dest = newNode;
        return;
    }
    
    Node *MergedSort(Node *a, Node *b){
        Node *dummy;  // This slight change gave me segmentation fault.
        Node *tail = dummy;
        dummy->next = NULL;
    
        while(1){
                if (a == NULL){
                        tail->next = b;
                        break;
                }
                else if (b == NULL){
                        tail->next = a;
                        break;
                }
                else if (a->data < b->data){
                        MoveNode(&(tail->next), &a);
                }
                else{
                        MoveNode(&(tail->next), &b);
                }
                tail = tail->next;
        }
        return (dummy->next);
    }
    

    我无法弄清楚,为什么程序在我执行此操作时崩溃,虽然早期的实现和后面的实现,在逻辑上看起来与我相同。

2 个答案:

答案 0 :(得分:2)

问题是当你这样做时

for (var i = 0; i < journal.length; i++) {
    var entry = journal[i];
    var index = 0;
    if (hasEvent(event, entry)) {
        index += 1;
    }

    if (entry.squirrel) {
        index += 2;
    }
    table[index] += 1;
}

dummy->next = NULL; 尚未初始化。取消引用未初始化的指针是未定义的行为。

您根本不需要dummy - 只需将dummy分配给NULL,将其重命名为tail,然后将head传递给{{1} }}。返回&head以完成修复:

MoveNode

Demo.

答案 1 :(得分:2)

dummy结构tail指向该结构的地址。结构的变量next指向NULL。到目前为止一切都很好。

Node dummy;
Node *tail = &dummy;
dummy.next = NULL;

dummy是指向结构的指针tail指向该结构的地址 - 好的。 (解除引用[1] - 不行)结构的变量next被非法访问,因为dummy尚未初始化。

Node *dummy;  // This slight change gave me segmentation fault.
Node *tail = dummy;
dummy->next = NULL;

[1] dummy->next相当于(*dummy).next