【问题标题】:Quicksort an array in C [closed]在C中快速排序数组[关闭]
【发布时间】:2015-01-09 01:46:39
【问题描述】:

我正在尝试使用 Quicksort 算法对一个包含 10 个整数的数组进行排序,下面是我的代码,它没有正确排序,有人可以指出我正在做的可能的错误吗?

int partition(int arr[], int first, int last)
{
    int pivot = arr[first];
    int low = first;
    int i = first + 1;
    while(i <= last){
        if(arr[i] < pivot){
            low++;
            swap(&arr[i], &arr[low]);
        }
        i++;
    }
    swap(&arr[first], &arr[low]);
    return low;
}

void quick_sort(int arr[], int first, int last)
{
    int pivot_pos;
    if(first < last){
        pivot_pos = partition(arr, first, last);
        quick_sort(arr, first, pivot_pos-1);
        quick_sort(arr, pivot_pos+1, last);
    }
}

【问题讨论】:

  • 清楚地描述您的问题。不要发布代码并期望人们为您修复它。
  • 为什么你同时标记了 c 和 c++ ?顺便说一句,我无法编译它!
  • 您可能想要查看Quicksort: Choosing the pivot,尽管您可能会发现这有点复杂(或者比您需要的更复杂)。你做了什么诊断打印?您是否检查过分区元素的值以及最后一个和第一个等?您还没有显示swap() 的代码;你知道这是否正确吗?
  • 好消息@JonathanLeffler !!

标签: c algorithm sorting quicksort


【解决方案1】:

这是您的代码的检测版本。由于您没有提供swap() 函数,所以我写了那个;我还写了dump_data() 来打印数组段的内容,并写了main() 用于测试。在我所做的有限测试的基础上,排序工作。鉴于您说没有,我怀疑您的swap() 代码可能有问题;要么是你的测试工具代码有问题(或者我的测试恰好是有效的情况!)。

#include <stdio.h>

static inline void swap(int *a, int *b) { int c = *a; *a = *b; *b = c; }

static void dump_data(const char *tag, int *data, int first, int last)
{
    printf("%s: (%d:%d)\n", tag, first, last);
    for (int i = first; i <= last; i++)
        printf(" %d", data[i]);
    putchar('\n');
}

static
int partition(int arr[], int first, int last)
{
    int pivot = arr[first];
    int low = first;
    int i = first + 1;
    while (i <= last)
    {
        if (arr[i] < pivot)
        {
            low++;
            swap(&arr[i], &arr[low]);
        }
        i++;
    }
    swap(&arr[first], &arr[low]);
    return low;
}

static
void quick_sort(int arr[], int first, int last)
{
    if (first < last)
    {
        dump_data("-->> QS", arr, first, last);
        int pivot_pos = partition(arr, first, last);
        printf("Pivot: arr[%d] = %d\n", pivot_pos, arr[pivot_pos]);
        quick_sort(arr, first, pivot_pos - 1);
        dump_data("-1-- QS", arr, first, pivot_pos - 1);
        quick_sort(arr, pivot_pos + 1, last);
        dump_data("-2-- QS", arr, pivot_pos + 1, last);
        dump_data("<<-- QS", arr, first, last);
    }
}

int main(void)
{
    int data[] = { 9, 2, 4, 7, 1, 3, 8, 6, 5 };
    int size = sizeof(data) / sizeof(data[0]);
    dump_data("Before", data, 0, size - 1);
    quick_sort(data, 0, size - 1);
    dump_data("After", data, 0, size - 1);
    return 0;
}

示例运行:

Before: (0:8)
 9 2 4 7 1 3 8 6 5
-->> QS: (0:8)
 9 2 4 7 1 3 8 6 5
Pivot: arr[8] = 9
-->> QS: (0:7)
 5 2 4 7 1 3 8 6
Pivot: arr[4] = 5
-->> QS: (0:3)
 3 2 4 1
Pivot: arr[2] = 3
-->> QS: (0:1)
 1 2
Pivot: arr[0] = 1
-1-- QS: (0:-1)

-2-- QS: (1:1)
 2
<<-- QS: (0:1)
 1 2
-1-- QS: (0:1)
 1 2
-2-- QS: (3:3)
 4
<<-- QS: (0:3)
 1 2 3 4
-1-- QS: (0:3)
 1 2 3 4
-->> QS: (5:7)
 7 8 6
Pivot: arr[6] = 7
-1-- QS: (5:5)
 6
-2-- QS: (7:7)
 8
<<-- QS: (5:7)
 6 7 8
-2-- QS: (5:7)
 6 7 8
<<-- QS: (0:7)
 1 2 3 4 5 6 7 8
-1-- QS: (0:7)
 1 2 3 4 5 6 7 8
-2-- QS: (9:8)

<<-- QS: (0:8)
 1 2 3 4 5 6 7 8 9
After: (0:8)
 1 2 3 4 5 6 7 8 9

更彻底的测试将自动验证结果是否确实已排序,并且还会有一个更大的数组,其中包含经过排序后检查确保没有更改的虚拟元素,并且会有多个不同大小的测试运行(包括 0 、1、2、3、4,然后是一些更大的尺寸)。这只是测试正确性。为了测试性能,你可以做一些事情,比如测试已经排序的数据,或者所有相同的值,或者反向排序的数据,或者风琴管的形成(∧ 和 ∨ 形式)等等,在数据中有和没有重复(以及随机序列)。

【讨论】:

    【解决方案2】:

    根据您的代码,即使是理解起来有点复杂的分区,qsort 函数也很好!我猜你的问题是交换功能!这是一个使用易于理解的分区函数实现的工作代码:

    void swap(int *a, int *b)
    {
        int temp;
        temp=*a;
        *a=*b;
        *b=temp;
    }
    
    
    /* the aim of the partition is to return the subscript of the exact */
    /* position of the pivot when it is sorted */
    // the low variable is used to point to the position of the next lowest element
    int partition(int arr[], int first, int last)
    {
        int pivot = arr[last]; // changed the pivot  
        int low = first;
        int i = first; // changed
        while(i <= last-1 ){// or you can do for(i=first;i<last;i++)
            if(arr[i] < pivot){
                swap(&arr[i], &arr[low]);
                low++; 
            }
            i++;
        }
        swap(&arr[last], &arr[low]);
        // after finishing putting all the lower element than the pivot 
        // It's time to put the pivot into its place and return its position
        return low;
    }
    
    
    
    void quick_sort(int arr[], int first, int last)
    {
        int pivot_pos;
        if(first < last){
            pivot_pos = partition(arr, first, last);
            quick_sort(arr, first, pivot_pos-1);
            quick_sort(arr, pivot_pos+1, last);
        }
    }
    

    要测试程序,你可以使用下面的 main 函数

    int main(int argc, char *argv[])
    {
        int tab[]={4,53,5,6,7,1};
        quick_sort(tab,0,5);
        int i=0;
        for (i=0;i<6;i++)
        {
            printf(" %d ",tab[i]);
        }
        printf("\n");
    
        return 0;
    }
    

    它将生成排序后的数组

    1 4 5 6 7 53
    

    如果你想看看到底发生了什么这是一个完整的代码:)

    #include <stdio.h> 
    
    void affiche(int *p,int size);
    void swap(int *p, int a, int b)
    {
        int temp=p[a];
            p[a]=p[b];
        p[b]=temp;
    }
    
    int partition(int *p, int start, int end)
    {
        int pindex=start;
        int pivot=p[end];
        int i=0;
        for (i=start;i<=end-1;i++)
        {
            if (p[i]<pivot)
            {
                printf("swap p[%d] and p[%d]    pivot %d\n",i,pindex,pivot);
                swap(p,i,pindex);
                affiche(p,7);
                pindex++;
            }
        }
                printf("==>swap p[%d] and p[%d]  pivot %d\n",pindex,end,pivot);
        swap(p,pindex,end);
        return pindex;
    }
    void quicksort(int *p,int a,int b)
    {
        if (a<b)
        {
            affiche(p,7);
            int pindex=partition(p,a,b);
            quicksort(p,a,pindex-1);
            quicksort(p,pindex+1,b);
        }
    }
    
    void affiche(int *p,int size)
    {
    int i=0;
    for (i=0;i<size;i++)
    {
        printf(" %d ",p[i]);
    }
    printf("\n");
    
    }
    int main(int argc, char *argv[])
    {
      int tab[]={7,2,4,8,4,0,4};
        affiche(tab,7); 
        quicksort(tab,0,6);
         affiche(tab,7); 
    
        return 0;
    }
    

    【讨论】:

    • 好奇:发现原来的分区函数效果很好。
    • 抱歉回复晚了:是的,你是对的@JonathanLeffler,他的代码似乎运行良好!我猜他的交换功能有问题!而且,分区比普通分区还真难懂!
    猜你喜欢
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多