W. :快速排序(利用分治法). 7.1,P85

//author: W.
//快速排序(利用分治法). 7.1,P85
//平均情况时间复杂度为O(nlgn),最坏情况为O(n^2)
//快速排序是就地排序,平均性能好,且常数因子很小,但最坏情况性能差,不过快排的平均情况与最佳情况运行时间很接近,如果输入是随机的,那么出现最坏情况的概率很小。


#include <stdio.h>

 

//为了让快排的性能更加接近平均性能,即降低最坏情况出现的概率,这里在PARTITION中选取x值时可以使用随机采样的方法
//随机采样x:利用一个随机函数产生出p~r中的一个随机值rand_index,用A[random_index]值作为x的值,这样即使输入是最坏情况,在排序中也会在很大的概率上为平均性能,见P90
//返回q的位置,使得A[p]~A[q-1] <= A[q] < A[q+1]~A[r]
int PARTITION(int A[], int p, int r)
{
    int x = A[r];
    int i = p-1;
    int j;
    int temp;
    //循环不变式满足条件:A[p]~A[i] <= x < A[i+1]~A[j-1],即分成2个部分,一部分小于x,一部分大于x,且这二部分挨着。
    //初始化:i == p-1, j == p, x == A[r], A[p]~A[i]无元素,A[i+1]~A[j-1]无元素,所以初始化成立
    for(j = p; j < r; ++j)//保持:A[j]标识每次待判断的元素,每次判断A[j]与x的大小关系,1)A[j] > x则A[j]应该放入大于x的部分中,那么直接++j即可,即增大第二部分。
    {                           //2)A[j] <= x,则A[j]应该放入小于x的部分中,那么只需要将A[j]与A[i+1](大于x部分的第一项)交换位置,并++i即可,同时++j,即增大第一部分。
        if(A[j] <= x)
        {
            temp = A[i+1];
            A[i+1] = A[j];
            A[j] = temp;
            ++i;
        }
    }
    //终止:终止时j == r,此时A[p]~A[i] <= x < A[i+1]~A[r-1]
    //下面把A[r]插入到正确位置,即A[i+1]处,即A[r]与A[i+1]交换
    A[r] = A[i+1];
    A[i+1] = x;
    return i + 1; //返回得到的q的位置
}

//利用分治法进行快速排序
//分解:每次把一个数组A[p]~A[r]中选取一个q,并处理数组A,使得A[p]~A[q-1] <= A[q] <= A[q+1]~A[r]。
//解决:通过递归的方式对分出的子序列进行排序。其中当p >= r时,则该子数组中无元素或只有一个元素,则无需再分,即最小问题情况。
//合并:因为每次分解时,二个子部分都是就地排序的,所以无需再合并,而在分解时,得出的q也是正确的位置,所以也无需合并。即经过递归解决后,数组已排序.
void QUICKSORT(int A[], int p, int r)
{
    if(p >= r)
    {
        return; //最小情况,已排序,直接返回。
    }
    int q = PARTITION(A, p, r);
    QUICKSORT(A, p, q-1);
    QUICKSORT(A, q+1, r);
}

void test_QuickSort()
{
    int a[] = { 5, 2, 4, 6, 1, 3, 10, 6, 7, 9, 8, 123, 233, 3, 23, 33, 1134, 454353, 2, 0, 0, 0, 1};
    int i;
    for(i = 0; i < sizeof(a)/sizeof(int); ++i)
    {
        printf("%d ", a[i]);
    }
    printf("/n");

    QUICKSORT(a, 0, sizeof(a)/sizeof(int)-1);
  
    for(i = 0; i < sizeof(a)/sizeof(int); ++i)
    {
        printf("%d ", a[i]);
    }
    printf("/n");
}

int main(int argc, char** argv)
{
    test_QuickSort();
    return 0;
}

//输出:
//5 2 4 6 1 3 10 6 7 9 8 123 233 3 23 33 1134 454353 2 0 0 0 1
//0 0 0 1 1 2 2 3 3 4 5 6 6 7 8 9 10 23 33 123 233 1134 454353

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值