快速排序优化

来源:互联网 发布:好用的安卓浏览器知乎 编辑:程序博客网 时间:2024/06/05 10:42

转载自:http://blog.csdn.net/wzy_1988/article/details/8043168

前言

今天要重写之前的快排算法,重新翻看自己之前的博客,总是会有稚嫩的感觉,这是好事,说明我一直在进步!

快排是分治策略很好的应用,IT面试大部分都会考察你对快排算法的掌握,博主面试阿里巴巴、创新工厂均在快排算法上有涉及,这里记录一下


算法思想

快速排序采用了一种分治策略,学术上称之为分治法(Divide-and-Conquer Method)

分治的基本思想

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

快排的思想

设当前需要排序的数组为int A[bt...ed]

分解:
在A[]中任选一个记录作为基准(pivot),以pivot为基准将数组A划分为两个小的数组A[bt...pivot-1]和A[pivot+1...ed],并使左边的数组元素均小于等于pivot,右边数组元素均大于等于piovt。此时,pivot处于正确的位置上,它不需要再参加后续的排序

求解:
递归的调用快速排序,对A[bt...pivot-1]和A[pivot+1...ed]进行快速排序

组合:
跟归并排序不同,因为每次调用快速排序,左右两个数组均已有序,因此对于快速排序来说,组合是一个空操作


实现代码(C语言)

快排用c实现其实可以直接调用系统的qsort函数,自己写compare比较函数即可,在php里是调用usort函数,但是面试考察大部分都是不能调用系统函数的,所以这里提供一下代码,供参考:

[cpp] view plaincopyprint?
  1. /** 
  2.  * 基准点排序 
  3.  * 
  4.  * T = O(n) 
  5.  * 
  6.  */  
  7. int pivotLoc(int *arr, int bt, int ed)  
  8. {  
  9.     int stand;  
  10.   
  11.     stand = arr[bt];  
  12.   
  13.     while (bt < ed) {  
  14.         while (bt < ed && arr[ed] >= stand)   ed --;  
  15.         if (bt < ed) arr[bt ++] = arr[ed];  
  16.   
  17.         while (bt < ed && arr[bt] <= stand)   bt ++;  
  18.         if (bt < ed) arr[ed --] = arr[bt];  
  19.     }  
  20.   
  21.     arr[bt] = stand;  
  22.   
  23.     return bt;  
  24. }  
  25.   
  26. /** 
  27.  * 快排入口代码,递归策略 
  28.  * 
  29.  * T = O(nlogn) 
  30.  * 
  31.  */  
  32. void quickSort(int *arr, int bt, int ed)  
  33. {  
  34.     int pivot;  
  35.   
  36.     if (bt < ed) {  
  37.         pivot = pivotLoc(arr, bt, ed);  
  38.         quickSort(arr, bt, pivot - 1);  
  39.         quickSort(arr, pivot + 1, ed);  
  40.     }  
  41. }  

优化

快排的平均时间复杂度是O(nlogn),但是考虑一下最坏的情况:

假设给定的排序序列是逆序,例如5、4、3、2、1,然后用上述快排代码进行从小到大排序,很明显,快排从O(nlogn)降到了O(n^2),如何避免这种情况呢?

解答:基准点的随机选取,我这里每次采用mid作为基准点

[cpp] view plaincopyprint?
  1. /** 
  2.  * 快排优化,随机选取基准点 
  3.  * 
  4.  */  
  5. void optimizeSort(int *arr, int bt, int ed)  
  6. {  
  7.     int mid = bt + ((ed - bt) >> 1);  
  8.   
  9.     // 不使用额外空间,进行两数互换  
  10.     if (arr[bt] != arr[mid]) {  
  11.         arr[bt] = arr[bt] ^ arr[mid];  
  12.         arr[mid] = arr[bt] ^ arr[mid];  
  13.         arr[bt] = arr[bt] ^ arr[mid];  
  14.     }  
  15. }  
  16.   
  17. /** 
  18.  * 基准点排序 
  19.  * 
  20.  * T = O(n) 
  21.  * 
  22.  */  
  23. int pivotLoc(int *arr, int bt, int ed)  
  24. {  
  25.     int stand;  
  26.       
  27.     // 快排优化  
  28.     if (bt < ed) {  
  29.         optimizeSort(arr, bt, ed);  
  30.     }  
  31.   
  32.     stand = arr[bt];  
  33.   
  34.     while (bt < ed) {  
  35.         while (bt < ed && arr[ed] >= stand)   ed --;  
  36.         if (bt < ed) arr[bt ++] = arr[ed];  
  37.   
  38.         while (bt < ed && arr[bt] <= stand)   bt ++;  
  39.         if (bt < ed) arr[ed --] = arr[bt];  
  40.     }  
  41.   
  42.     arr[bt] = stand;  
  43.   
  44.     return bt;  
  45. }  
  46.   
  47. /** 
  48.  * 快排入口代码,递归策略 
  49.  * 
  50.  * T = O(nlogn) 
  51.  * 
  52.  */  
  53. void quickSort(int *arr, int bt, int ed)  
  54. {  
  55.     int pivot;  
  56.   
  57.     if (bt < ed) {  
  58.         pivot = pivotLoc(arr, bt, ed);  
  59.         quickSort(arr, bt, pivot - 1);  
  60.         quickSort(arr, pivot + 1, ed);  
  61.     }  
  62. }  
阅读(5) | 评论(0) | 转发(0) |
0

上一篇:直白快速排序算法,C语言实现

下一篇:移位运算(左移和右移)

相关热门文章
  • 堆和栈的区别
  • select,poll,epoll区别
  • 浅淡淘宝内核对LVS的性能优化...
  • 英特尔1亿美元成立中国智能设...
  • SEOer分析导致首页被K的几个因...
  • test123
  • 编写安全代码——小心有符号数...
  • 使用openssl api进行加密解密...
  • 一段自己打印自己的c程序...
  • sql relay的c++接口
  • 我的ChinaUnix博客被锁定了,...
  • 怎样破解雅虎邮箱密码...
  • 虚拟机中ubuntu无线连接问题...
  • IBM DS3400 盘阵怎么查看是单...
  • 启动auditd时,报错如下,怎么...
评论热议
0 0
原创粉丝点击