【问题标题】:Merging two sorted lists by using linked lists使用链表合并两个排序列表
【发布时间】:2016-03-30 14:00:28
【问题描述】:

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

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

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

这是我执行此任务的代码:

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 的指针,它会给我分段错误。这是错误的代码,稍作改动,dummy 的声明现在是 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);
}

我无法弄清楚为什么当我这样做时程序会崩溃,尽管早期的实现和后面的实现在逻辑上对我来说看起来是一样的。

【问题讨论】:

  • Node 长什么样子?
  • dummy-&gt;next = NULL;。这是无效的,因为 dummy 没有初始化。很可能会导致该行出现段错误。
  • 我在代码中添加了Node的定义。请看一看。
  • 但同样的 un 初始化在前一个实现中唯一的区别是 dummy 不是指向节点的指针

标签: c


【解决方案1】:

问题是当你这样做时

dummy->next = NULL;

dummy 尚未初始化。取消引用未初始化的指针是未定义的行为。

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

Node *MergedSort(Node *a, Node *b) {
    Node *head = NULL;
    Node **tail = &head;
    while(1) {
        if (a == NULL){
            *tail = b;
            break;
        } else if (b == NULL){
            *tail = a;
            break;
        } else if (a->data < b->data){
            MoveNode(tail, &a);
        } else{
            MoveNode(tail, &b);
        }
        tail = &((*tail)->next);
    }
    return head;
}

Demo.

【讨论】:

  • 我这样做是因为我总是在列表的尾部添加元素,如果我不使用 dummy 我将失去对列表头部的访问权限,因为尾部总是指向尾部的列表。
  • @AnkitMishra 您可以单独保留指向head 的指针。有关详细信息,请参阅编辑和演示。
  • 非常感谢,我得到了这个问题,你的实现,彻底解决了这个问题。
  • @AnkitMishra 欢迎您!如果问题已解决,请考虑通过单击旁边的灰色复选标记来接受答案。这将使其他网站访问者知道问题已解决,并为您赢得 Stack Overflow 上的新徽章。
【解决方案2】:

dummy 是一个结构tail 指向该结构的地址。结构的变量next 指向NULL。到目前为止一切顺利。

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

dummy 是一个指向结构的指针tail 指向该结构的地址 - 好的。 (dereferenced[1] - NOT OK) 结构的变量next 被非法访问,因为dummy 尚未初始化。

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

[1] dummy-&gt;next 等价于(*dummy).next

【讨论】:

    猜你喜欢
    • 2012-10-31
    • 2011-01-21
    • 2015-05-12
    相关资源
    最近更新 更多