排序算法整理(3)快速排序

本文深入探讨快速排序算法,从基本原理出发,详细介绍其实现过程,并通过荷兰三色旗问题进行拓展,展示快速排序的高效性和灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

貌似需要整理一下排序算法了,正好最近在看的宋劲杉的《LINUX一站式编程》也提到了几个排序算法,于是决定把几个常见的排序算法都写写吧。

快速排序是我觉得排序算法中趣味排名top 1的排序。

快速排序每次只做一件事儿。在当前数组中,找到一个元素(叫做pivot),然后把比pivot小的放在pivot的左边,把比pivot打的放在pivot的右边。这样一趟下来,pivot被排好序了。也就是说,每趟就排序一个数。这个过程一般用函数partition(){}来表达。

然后,对pivot左边的数组重复刚才的那趟过程。

然后,对pivot右边的数组也重复刚才的那趟过程。

当最后发现每个数组都只有1个元素的时候,就OK了。

和归并排序一样,快速排序也使用了分治的思想, 所以时间复杂度都是Θ(n lg n)但是,快速排序比归并排序牛的地方在于,首先,快速排序的常数因子更小,也就是说,平均下来,虽然快速排序和归并排序是同一量级的时间复杂度,但是快速排序的需要时间比归并排序的需要时间少。第二,快速排序就地解决,无需额外空间,归并排序需要额外空间。

(theconstant factors hidden in the Θ(n lg n) notation are quite small  theadvantage of sorting in place 《CLRS算法导论》)

这里有个视频,展示快速排序的声音。

//下面两个函数用来依次打印数组。功能一样,参数不一样,这是为了方便不同的数据类型的调用要求。

void print_num_1(uint32_t* arr, uint32_t len){
    for(int i=0;i<len;i++)
        std::cout<<arr[i]<<"\t";
    std::cout<<std::endl;
    return;
}

void print_num_2(int* arr, int len){
    for(int i=0;i<len;i++)
        std::cout<<arr[i]<<"\t";
    std::cout<<std::endl;
    return;
}
下面是快速排序的过程

//quick_sort_version_1
int partition(int* arr, int st, int ed){
    int j=st;
    int i=j-1;
    int pivot=arr[ed];
    int temp;
    while (j<=ed-1) {
        if (pivot>arr[j]) {
            i++;
            temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
        }
        j++;
    }

    i++;
    temp=arr[ed];
    arr[ed]=arr[i];
    arr[i]=temp;
    //print_num_2(arr+st,ed-st+1);
    return i;
}
void quick_sort_1(int* arr, int st, int ed){  
    if(st<ed) {
        int pivot=partition(arr, st, ed);
        quick_sort_1(arr,st, pivot-1);
        quick_sort_1(arr,pivot+1,ed);
    }
}

后来,又看到了一个荷兰三色旗问题,于是扩展了一下快速排序的做法,详见 这里



快速排序算法(C语言版) #include <stdio.h> #include "type.h" #define Q_SIZE 10 /************************************* 模块内部数组或变量定义 **************************************/ static UINT8 q_array[Q_SIZE] = {0}; //static UINT8 m_array_tmp[M_SIZE] = {0}; /* 辅助数组,存放排序的中间结果 */ /************************************* 函数定义 **************************************/ /******************************************************************************************* 函数名:UINT8 splt( UINT8 * m_ptr, UINT8 q_low, UINT8 q_high, UINT8 q_pos ) 入口参数列表:m_ptr, q_pos 入口参数描述:数组的地址,数组的首元素尾元素位置,指向主元位置的指针 返回值描述:无 函数功能:使数组经过排列后小于或等于x的元素在x前面,x在大于它的元素前面(x = q_array[*q_pos]) ********************************************************************************************/ UINT8 splt( UINT8 * q_ptr, SINT8 q_low, SINT8 q_high ) { UINT8 x = 0; SINT8 i = 0; SINT8 j = 0; UINT8 q_tmp = 0; i = q_low; x = q_ptr[q_low]; for (j = q_low + 1; j <= q_high; j++) { if (q_ptr[j] <= x) { i++; if (i != j) { q_tmp = q_ptr[i]; q_ptr[i] = q_ptr[j]; q_ptr[j] = q_tmp; } } } q_tmp = q_ptr[i]; q_ptr[i] = q_ptr[q_low]; q_ptr[q_low] = q_tmp; return i; } /******************************************************************************************* 函数名:void quicksort( UINT8 * m_ptr, UINT8 m_low, UINT8 m_high ) 入口参数列表:m_ptr, m_low, m_high 入口参数描述:数组的地址,数组的首元素尾元素的索引 返回值描述:无 函数功能:对数组进行排序,产生非降序的数组 ********************************************************************************************/ void quicksort( UINT8 * q_ptr, SINT8 q_low, SINT8 q_high ) { UINT8 q_w; if (q_low < q_high) { q_w = splt(q_ptr, q_low, q_high); quicksort(q_ptr, q_low, q_w - 1); quicksort(q_ptr, q_w + 1, q_high); } } /****************************************************************************** 函数名:main( void ) 入口参数列表:无 入口参数描述:无 返回值描述:无 函数功能:主函数,用于测试 *******************************************************************************/ void main( void ) { UINT8 i, q_num = 0; printf("请输入10个2位整数:\n"); for (i = 0; i < Q_SIZE; i++) { scanf("%d", &q_num); q_array[i] = q_num; } quicksort(q_array, 0, 9); for (i = 0; i < Q_SIZE; i++) { printf("%d ", q_array[i]); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值