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); } }
更多方法请参考: