快速排序(c语言实现)

1.起因

今天在acm刷题的时候,之前的排序算法一直都是冒泡,可能九度OJ的难度题考察的都是快速排序,导致我都是死在time limited上,因此我下决心要学习一下快速排序,心得跟大家进行分享!


2.算法思想

快速排序采用了一种分治策略,我感觉它就是归并排序的优化,学术上称之为分治法(Divide-and-ConquerMethod)

(1)分治的基本思想:

将原问题分解成若干个规模更小但是结构跟原问题相似的子问题。递归的解决这些子问题,然后将这些子问题的解喝并为原问题的解

(2)快速排序的思想:

设当前需要排序的数组为int A[low..high]
分解:
在A[]中任选一个记录作为基准(pivot),以pivot为基准将数组A划分为两个小的数组A[low..pivot-1]和A[pivot+1..high],并使左边的数组元素均小于等于pivot,右边数组元素均大于等于piovt。此时,pivot处于正确的位置上,它不需要再参加后续的排序
求解:
递归的调用快速排序,对A[low..pivot-1]和A[pivot+1..high]进行快速排序
组合:
跟归并排序不同,因为每次调用快速排序,左右两个数组均已有序,因此对于快速排序来说,组合是一个空操作

3.快速排序程序实现

主流程:

  1. /**
  2. *Description:快速排序主流程
  3. */
  4. voidquicksort(int*A,intp,intr)
  5. {
  6. intpivot;
  7. if(p<r)
  8. {
  9. pivot=partition(A,p,r);
  10. quicksort(A,p,pivot-1);
  11. quicksort(A,pivot+1,r);
  12. }
  13. }

注意:为排序整个数组,只需要在main函数中调用一个quicksort(A,begin,end)即可完成对数组的排序

划分实现:

  1. /**
  2. *Description:快速排序寻找基准点
  3. */
  4. intpartition(int*A,intp,intr)
  5. {
  6. intleft=p;//从左往右扫描
  7. intright=r;//从右往左扫描
  8. intstand=A[p];//基准
  9. //从区间两端向中间扫描,直到left==right为止
  10. while(left<right)
  11. {
  12. while(left<right&&A[right]>=stand)
  13. {
  14. right--;
  15. }
  16. if(left<right)
  17. A[left++]=A[right];
  18. while(left>right&&A[left]<=stand)
  19. {
  20. left++;
  21. }
  22. if(left<right)
  23. A[right--]=A[left];
  24. }
  25. //基准最后的定位位置
  26. A[left]=stand;
  27. returnleft;
  28. }


4.算法分析

快速排序的主要时间消耗在划分操作上,对长度为len的数组进行划分,需要len-1次关键字的比较

(1)最坏的时间复杂度

最坏的情况是每次划分的基准都是当前无序区中最大(最小)的记录,划分的结果是基准左边的区间为空(基准为最小记录)或者基准右边的区间为空(基准为最大记录),划分所得的非空子区间中记录的数目仅仅比划分前的无序区元素数少一。
因此,快速排序最坏情况下需要做n-1次划分,第i次划分的区间长度为n-i+1,第i次所需比较的次数为n-i,故而最话情况下的时间复杂度为:T(n)= (n-1)(n)/2 = O(n*n)

(2)最好情况下的时间复杂度

每次划分选取的基准都是当前无序区间的中值,时间复杂度为:T(n)= 0(n*lgn)

(3)平均情况下的时间复杂度

平均性能,快速排序是最好的,所以我也建议在ACM刷题的时候尽量用快速排序来时间对数组的排序功能。


之后,我会带来一道用快速排序AC的题目
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值