经典排序算法(2)——快速排序算法详解
快速排序(Quick Sort)也是一種典型的交換排序算法,通過交換數據元素的位置進行排序。
一、算法基本思想
(1)基本思想
快速排序的基本思想就是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。快速排序采用了分治法來解決問題。
(2)運行過程
快速排序算法的運行過程如下::
1、從序列中挑出一個元素,稱為“基準”(pivot)。一般是選取序列的第一個元素。
2、重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準的后面(相同的數可以到任一邊)。在這個分區結束之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作。
3、遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。
4、直到序列的大小是0或1,也就是所有元素都已經被排序好了,遞歸結束。
(3)示例
1、一次快速排序過程
所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準的后面,最后找到基準元素的位置。
2、整個快速排序過程
二、算法實現(核心代碼)
C++實現:
void swap(int *x, int *y) {int t = *x;*x = *y;*y = t; } void quick_sort_recursive(int arr[], int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(&arr[left], &arr[right]);}if (arr[left] >= arr[end])swap(&arr[left], &arr[end]);elseleft++;quick_sort_recursive(arr, start, left - 1);quick_sort_recursive(arr, left + 1, end); } void quick_sort(int arr[], int len) {quick_sort_recursive(arr, 0, len - 1); }
Java實現:
class quick_sort {int[] arr;private void swap(int x, int y) {int temp = arr[x];arr[x] = arr[y];arr[y] = temp;}private void quick_sort_recursive(int start, int end) {if (start >= end)return;int mid = arr[end];int left = start, right = end - 1;while (left < right) {while (arr[left] < mid && left < right)left++;while (arr[right] >= mid && left < right)right--;swap(left, right);}if (arr[left] >= arr[end])swap(left, end);elseleft++;quick_sort_recursive(start, left - 1);quick_sort_recursive(left + 1, end);}public void sort(int[] arrin) {arr = arrin;quick_sort_recursive(0, arr.length - 1);} }
三、算法改進和變種
對于快速排序改進的方法,可以參考《大話數據結構這本書》。快速排序的優點在于,對于大量數據的時候,很容易將某個元素放到對應的位置。而快速排序的缺點也很明顯:
一是如果原始數據就是有序的,那么快速排序過程中對序列的劃分就十分不均勻,將序列分為了1和n-1的大小(而通常希望的最理想狀態是二分);
二是對于小數組進行排序時,也需要遞歸進行幾次才能將數據放到正確的位置;
三是排序快速是不穩定的,當重復數據很多時效率比較低。
針對快速排序的缺點,對于快速排序主要有以下三個改進方案:
(1)優化選取基準pivotkey — — 三數取中法
三數取中法的思想如下:選取序列左端、中間和右端三個數據元素,按大小進行排序,選擇中間大小的元素作為基準。
(2)序列較小時使用插入排序代替快速排序
在遞歸過程,當排序的子序列小于預定的值M時,采用插入插入排序。
(3)重復元素較多使用三分區法
通過劃分讓相等的元素連續地擺放,然后只對左側小于V的序列和右側大于V對的序列進行排序。
如上圖: 從左至右掃描數組,維護一個指針lt使得[lo…lt-1]中的元素都比v小,一個指針gt使得所有[gt+1….hi]的元素都大于v,以及一個指針i,使得所有[lt…i-1]的元素都和v相等。元素[i…gt]之間是還沒有處理到的元素,i從lo開始,從左至右開始掃描:
1、如果a[i]<v::交換a[lt]和a[i],lt和i自增;
2、如果a[i]>v:交換a[i]和a[gt],,gt自減;
3、如果a[i]=v:i自增。
四、算法性能(時間復雜度、空間復雜度、穩定性分析)
快速排序是通常被認為在同數量級(O(nlog2n))的排序方法中平均性能最好的。
但若初始序列按關鍵字有序或基本有序時,快排序反而蛻化為冒泡排序,也就是說快速排序最壞情況下時間復雜度為O(n^2),空間復雜度為O(n)。
如果每次排序時所選的基準都能講序列進行二分,那么此時的快速排序效果最好,也就是說快速排序在最好情況下的時間復雜度為O(nlogn),空間復雜度為O(logn)。
快速排序的平均時間復雜度為O(nlogn),空間復雜度為O(logn)。快速排序是一種不穩定的排序算法。
參考文獻:
1、淺談算法和數據結構: 四 快速排序?http://www.cnblogs.com/yangecnu/p/Introduce-Quick-Sort.html
2、快速排序算法及其改進算法實現?http://blog.csdn.net/lsjseu/article/details/9749587
3、快速排序及改進?http://flyingdutchman.iteye.com/blog/1863691
4、快速排序(2)算法改進--小的子文件、三者取中、重復關鍵字三路劃分序及改進?https://www.zybuluo.com/quinn/note/78606
5、怎樣讓快速排序最快??http://blog.sina.com.cn/s/blog_4dff8712010136jh.html
總結
以上是生活随笔為你收集整理的经典排序算法(2)——快速排序算法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑客这么设让电脑全自动清理电脑黑客如何清
- 下一篇: 经典排序算法(3)——直接插入排序算法详