1、概念html
快速排序由C.A.R.Hoare在1962年提出,是冒泡排序的一種改進。其基本思想爲:經過一趟排序將待排序數據分割成獨立的兩部分,其中一部分的全部值都比另外一部分的全部值都小,而後再對分割的兩部分分別進行快速排序,整個過程能夠遞歸進行,最終全部數據變爲有序序列。算法
2、算法要點數組
假設待排序數組爲a[0], a[1],…a[n-1],快速排序步驟如下:dom
一、初始化兩個變量i、j,剛開始i = 1,j=n-1。oop
二、將第一個元素a[0]做爲基準數。ui
三、從i開始向後搜索,找到第一個大於基準數的元素a[i]。spa
四、從j開始向前搜索,找到第一個小於等於基準數的元素a[j]。code
五、將a[i]與a[j]互換。htm
六、重複3到5步驟,直到i = j + 1,此時,j指向的元素是最後一個(從左邊算起)小於等於中軸的元素,而後將a[0]與a[j]對換。blog
七、序列被基準數分割成兩個分區,前面分區所有小於等於基準數,後面分區所有大於基準數。
八、遞歸對分區子序列進行快速排序,最終完成整個排序工做。
每趟快速排序的核心工做是:
選一個元素做爲基準數,而後將全部比它小的數都放到它前面,大於它的數都放在它後面。
3、算法實現
實現一:
1 using System; 2 using System.Collections.Generic; 3 4 namespace QuickSort 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 QuickSortUnitTest(13); 11 12 } 13 private static void QuickSort(List<int>dataList, int left, int right) 14 { 15 if(left < right)//遞歸的邊界條件,當left等於right時,元素個數爲1個 16 { 17 int pivot = dataList[left];//最左邊的元素做爲中軸 18 int i = left + 1; 19 int j = right; 20 int tmp = 0; 21 //當i == j時,i和j同時指向的元素尚未與中軸元素判斷, 22 //小於等於中軸元素,i++,大於中軸元素j--, 23 //當循環結束時,必定有i = j + 1, 且i指向的元素大於中軸,j指向的元素小於等於中軸 24 while (i <= j) 25 { 26 while(i <= j && dataList[i] <= pivot)//從前向後找到第一個大於pivot的元素 27 { 28 i++; 29 30 } 31 while(i <= j && dataList[j] > pivot) 32 { 33 j--; 34 35 } 36 if(i < j) 37 { 38 tmp = dataList[i]; 39 dataList[i] = dataList[j]; 40 dataList[j] = tmp; 41 } 42 } 43 //當循環結束時,j指向的元素是最後一個(從左邊算起)小於等於中軸的元素 44 //將中軸元素和j所指的元素互換 45 tmp = dataList[left]; 46 dataList[left] = dataList[j]; 47 dataList[j] = tmp; 48 Console.WriteLine(); 49 foreach (var item in dataList) 50 { 51 Console.Write($" {item} "); 52 } 53 Console.WriteLine(); 54 QuickSort(dataList, left, j - 1); 55 QuickSort(dataList, j + 1 , right); 56 } 57 } 58 private static void QuickSortUnitTest(int loopNum) 59 { 60 Random random = new Random(); 61 List<int> dataList = new List<int>(); 62 for (int i = 0; i < loopNum; i++) 63 { 64 dataList.Add(random.Next(100)); 65 } 66 Console.Write("Original data:"); 67 foreach(var item in dataList) 68 { 69 Console.Write($" {item} "); 70 } 71 72 QuickSort(dataList, 0, dataList.Count - 1); 73 Console.Write("Quick sorted data:"); 74 75 foreach (var item in dataList) 76 { 77 Console.Write($" {item} "); 78 } 79 Console.WriteLine(); 80 } 81 } 82 }
實現二:
基本思想:「挖坑填坑」
使用兩個變量i和j分別指向最左邊和最右邊的元素,咱們將首元素做爲中軸,並複製到變量pivot中,這時咱們能夠將首元素i所在的位置當作一個坑,咱們從j的位置從右向左掃描,找一個小於等於中軸
的元素A[j],來填補A[i]這個坑,填補完成後,拿去填坑的元素所在的位置j又能夠看作一個坑,這時咱們在以i的位置從前日後找一個大於中軸的元素來填補A[j]這個新的坑,如此往復,直到
i和j相遇(i == j,此時i和j指向同一個坑)。
最後咱們將中軸元素放到這個坑中。而後,咱們按照相同的方法分別對左右兩個數組執行相同的操做。
private static void QuickSort2(List<int>dataList, int left, int right) { if(left < right) { //最左邊的元素做爲中軸複製到pivot,這時最左邊的元素能夠看作一個坑 int pivot = dataList[left]; //注意這裏 i = L,而不是 i = L+1, 由於i表明坑的位置,當前坑的位置位於最左邊 int i = left; int j = right; while(i < j) { //下面面兩個循環的位置不能顛倒,由於第一次坑的位置在最左邊 while (i < j && dataList[j] > pivot) { j--; } //填A[i]這個坑,填完後A[j]是個坑 //注意不能是A[i++] = A[j],當因i==j時跳出上面的循環時 //坑爲i和j共同指向的位置,執行A[i++] = A[j],會致使i比j大1, //但此時i並不能表示坑的位置 dataList[i] = dataList[j]; while(i < j && dataList[i] <= pivot) { i++; } dataList[j] = dataList[i]; } //循環結束後i和j相等,都指向坑的位置,將中軸填入到這個位置 dataList[i] = pivot; QuickSort2(dataList, left, i - 1); QuickSort2(dataList, i + 1, right); } }
更多方法請參考: