链表的单个函数mergesort中的段错误

时间:2016-09-15 02:39:39

标签: c++

我正在使用在线C ++编译器遇到分段错误,而整天做这个单一函数mergesort并且找不到它可能的位置。另一个问题是,我不理解这种查找链表中间的方法,为什么是赋值运算符,有没有更好的方法呢?任何帮助将不胜感激。

#include <stdio.h>
#include <stdlib.h>

struct listnode { struct listnode * next; int key; };

struct listnode * sort(struct listnode * a)
{
    struct listnode  *fast, *slow, *mid, *left, *right;
    fast = a; left = a; right = NULL;  mid = NULL;

    //data is null or one node
    if (!a || !a->next)
    {
        return a;
    }

    //find mid by declaring a pointer skipping throw an extra node for each loop

    while (fast)
    {
        if (fast = fast->next) { fast = fast->next; }
        mid = slow;
        slow = slow->next;
    }

    //split the list in recursion
    if (mid != NULL) { mid->next = NULL; }

    a = sort(a); slow = sort(slow);

    //merge
    while (left != NULL && slow != NULL)
    {
        if (left->key < right->key) { left->next = mid; right = left; }
        else
        {
            if (!right)
                a = slow;
            else
            {
                right = slow; right->next = slow;  slow = slow->next; right->next = left;
            }
        }

    }
    if (left == NULL) { right->next = slow; }
    return(a);

}


//test 


int main()
{
    long i;
    struct listnode *node, *tmpnode, *space;
    space = (struct listnode *) malloc(500000 * sizeof(struct listnode));
    for (i = 0; i< 500000; i++)
    {
        (space + i)->key = 2 * ((17 * i) % 500000);
        (space + i)->next = space + (i + 1);
    }
    (space + 499999)->next = NULL;
    node = space;
    printf("\n prepared list, now starting sort\n");
    node = sort(node);
    printf("\n checking sorted list\n");
    for (i = 0; i < 500000; i++)
    {
        if (node == NULL)
        {
            printf("List ended early\n"); exit(0);
        }
        if (node->key != 2 * i)
        {
            printf("Node contains wrong value\n"); exit(0);
        }
        node = node->next;
    }
    printf("Sort successful\n");
    exit(0);
}

1 个答案:

答案 0 :(得分:3)

至少有一个问题是:

while (fast)
{
    if (fast = fast->next) { fast = fast->next; }
    mid = slow;
    slow = slow->next; // <-------- HERE!
}
在此循环之前,

fast被指定为非空值,因此控件进入循环并尝试读取slow->next,这是无效的。 slow指针未在循环之前分配给任何内容,因此它保存垃圾值并且不指向有效的内存位置。因此,通过该指针读取存储器很可能违反进程地址空间。从语言的角度来看,读取未初始化的指针是undefined behavior的一个例子。

另请参阅this问题中的一个很好的解释。