双向链表上的快速排序导致错误的指针?

时间:2014-02-11 20:00:39

标签: c linked-list quicksort

我写这篇文章是为了理解各种排序算法并判断在不同情况下效果最好的练习的一部分。因为我从未真正学过它们:(

这是我对维基百科的伪代码的解释,为速度添加了额外的“相等”列表(希望如此)。以及其他一些小的补充。一旦排序结束(剩下2或3个节点),我的程序就会崩溃。该程序按降序排序。

GDB在while循环中指示它与top变量的错误指针。显然它没有列表末尾的空指针。我怀疑快速列表功能很好,但它是导致问题的支持功能之一。我需要帮助发现我做错了什么

快速排序:

void quicksort(NODE **top,NODE **last,int * size)
{
    if((*size)>3)
    {
        NODE *pivot = pop(last);
        *last=0;
        NODE *greater_node=0;int greater=0; NODE * glast=0;
        NODE *equal_node=0;int equal=0;
        NODE *less_node=0;int less=0; NODE * llast=0;
        int pivot_value=pivot->value;
        int value_at=0;
        while(*top)
        {
            value_at=(*top)->value;
            if(value_at>pivot_value)
            {
                push2(&greater_node,pop(top));
                if(!greater) { glast=greater_node; }
                greater++;
            }
            if(value_at<pivot_value)
            {
                push2(&less_node,pop(top));
                if(!less) { llast=less_node; }
                less++;
            }
            else
            {
                push2(&equal_node,pop(top));
                equal++;
            }
        }
        quicksort(&greater_node,&glast,&greater);
        quicksort(&less_node,&llast,&less);
        cat(&equal_node,less_node);
            cat(&pivot,equal_node);
        cat(&greater_node,pivot);
            *top=greater_node;
        *size = greater+less+equal+1;
    }
    else if((*size)==3)
    {
        NODE *a=(*top);
        NODE *b=(*top)->next;
        NODE *c=(*top)->next->next;
        if(a->value<b->value) { swap(&(a->value),&(b->value)); }
        if(b->value<c->value) { swap(&(b->value),&(c->value)); }
        if(a->value<b->value) { swap(&(a->value),&(b->value)); }
    }
    else if((*size)==2)
    {
            if((*top)->value<(*top)->next->value) swap(&((*top)->value),&((*top)->next->value));
    }
}

2 个答案:

答案 0 :(得分:2)

我没有达到快速排序功能本身,但你的pop()看起来很可疑。具体来说,如果*top指向第一个元素,那么

        (*top)=(*top)->next;

会在你有机会做任何有用的事情之前消灭*top

我的总体建议是找到代码出现故障的最简单输入,并在调试器中逐步执行程序,观察正在发生的事情。这可以让您确定事情开始偏离计划的确切时刻。

另一种策略是为每个函数提供一系列单元测试,以单独测试每个构建块。

答案 1 :(得分:0)

我不想让事情得不到解决。 IDK,如果我实际修改核心功能与其他方法相比。特别是pop功能。但我以为我会发布完整性。

void quicksort(NODE **top,NODE **last,int * size)
{
    if((*size)>3)
    {
        NODE *pivot = pop(last);
        NODE *greater_node=0;int greater=0; NODE * glast=0;
        NODE *equal_node=0;int equal=0;
        NODE *less_node=0;int less=0; NODE * llast=0;
        int pivot_value=pivot->value;
        int value_at=0;
        while(*top)
        {
            value_at=(*top)->value;
            if(value_at>pivot_value)
            {
                push2(&greater_node,pop(top));
                if(!greater) { glast=greater_node; }
                greater++;
            }
            else if(value_at<pivot_value)
            {
                push2(&less_node,pop(top));
                if(!less) { llast=less_node; }
                less++;
            }
            else
            {
                push2(&equal_node,pop(top));
                equal++;
            }
        }
        quicksort(&greater_node,&glast,&greater);
        quicksort(&less_node,&llast,&less);
        if(less) { cat(&equal_node,less_node); }
            cat(&pivot,equal_node);
        cat(&greater_node,pivot);
            *top=greater_node;
        *size = greater+less+equal+1;
    }
    else if((*size)==3)
    {
        NODE *a=(*top);
        NODE *b=(*top)->next;
        NODE *c=(*top)->next->next;
        if(a->value<b->value) { swap(&(a->value),&(b->value)); }
        if(b->value<c->value) { swap(&(b->value),&(c->value)); }
        if(a->value<b->value) { swap(&(a->value),&(b->value)); }
    }
    else if((*size)==2)
    {
        NODE *a=(*top);
        NODE *b=(*top)->next;
        if(a->value<b->value) { swap(&(a->value),&(b->value)); }
        //if((*top)->value<(*top)->next->value) swap(&((*top)->value),&((*top)->next->value));
    }
}