快速排序

快速排序

快速排序是一种基于分治法的排序方法,每一趟快排选择序列中任一个元素作为枢轴(pivot)(通常选第一个元素),将序列中比枢轴小的元素都移到枢轴前边,比枢轴大的元素都移到枢轴后边。


分治法:

第一步首先将原问题分解成若干个子问题,这个子问题只是原问题较小规模的实例。

第二步将解决这些子问题,递归地求解各子问题。递归的边界就是问题规模足够小的时候,可以直接求解。


算法性能

时间复杂度:最好情况下时间复杂度为O(nlogn) ,待排序序列越无序,算法效率越高。

                      最坏情况下时间复杂度为O(n2),待排序序列越有序,算法效率越低。

递归复杂度的表达式:T(n) = aT(n/b) + f(n) 

n/b是子问题的大小,比如快排每次划分子问题之后的大小,a是子问题大小的数量,f(n)是分解问题和合并问题所需要的时间

1)快速排序最优的情况就是每一次Partition取到的元素都刚好平分整个数组 即a=b=2  f(n)=O(n)=Θ(n)   T(n)=O(nlogn)

2)快速排序最坏的情况就是每一次Partition取到的元素在一端,即T(n)=T(n-1)+T(0)+f(n)=T(n-1)+f(n)=T(n-2)+f(n)+f(n-1)=……=f(1)+f(2)+……+f(n)(等差数列)=O(n2)

空间复杂度:由于快速排序是递归的,需要借助一个递归工作栈来保存每一层递归调用的必要信息,其容量应与递归调用的最大深度一致。

最好情况下为 log2(n+1)(每次partition都很均匀)递归树的深度O(logn)

最坏情况下,因为要进行n-1次递归调用,所以栈的深度为O(n)

稳定性:快速排序是不稳定的,是因为存在交换关键字


实现代码

/**
 * 快速排序
 */

#include <stdio.h>

// 数组长度
#define LENGTH(array) ( (sizeof(array)) / (sizeof(array[0])) )

/*
 * 快速排序
 *
 * 参数说明:
 *     arr -- 待排序的数组
 *     low -- 数组的左边界(例如,从起始位置开始排序,则low=0)
 *     high -- 数组的右边界(例如,排序截至到数组末尾,则high=arr.length-1)
 */
void quickSort(int arr[], int low, int high)
{
	  int i=low,j=high,temp;
    if (low < high)
    {
        temp = arr[i];//暂存low里面的关键字 
        while (i < j)
        {
            while(i < j && arr[j] > temp)
                j--; // 从右向左找第一个小于temp的数
            if(i < j)
                arr[i++] = arr[j];
            while(i < j && arr[i] < temp)
                i++; // 从左向右找第一个大于temp的数
            if(i < j)
                arr[j--] = arr[i];
        }
        arr[i] = temp;
        quickSort(arr, low, i-1); /* 递归调用 */
        quickSort(arr, i+1, high); /* 递归调用 */
    }
}

void main()
{
    int i;
    int arr[] = {30,40,88,554,60,10,20,50};
    int ilen = LENGTH(arr);

    printf("排序前:");
    for (i=0; i<ilen; i++)
        printf("%d ", arr[i]);
    printf("\n");

    quickSort(arr, 0, ilen-1);

    printf("排序后:");
    for (i=0; i<ilen; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

 

显示界面

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值