0.简介
快速排序是由冒泡排序改进而得的。在冒泡排序过程中,只对相邻的两个记录进行比较,因此每次交换两个相邻记录时只能消除一个逆序。如果能通过两个(不相邻)记录的一次交换,消除多个逆序,则会大大加快排序的速度。快速排序方法中的一次交换可能消除多个逆序
1.算法思想
在待排序的n个记录中任取一个记录(通常取第一个记录)作为枢轴,设其关键字为pivotkey。经过一趟排序后,把所有关键字小于pivotkey的记录交换到前面,把所有关键字大于pivotkey的记录交换到后面,结果将待排序记录分为两个子表,最后将枢轴放置在分界处的位置。然后,分别对左右子表重复上述过程,直至每一个子表只有一个记录时,排序完成
其中,一趟快速排序的具体做法如下:
a.设两个指针low和high,初始时分别指向表的下界和上界,设枢轴记录的关键字pivotkey(第一趟时,low=1;high=L.length)
b.从表的最右侧位置,依次向左搜索找到第一个关键字小于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若high所指记录的关键字大于等于pivotkey,则向左移动指针high(执行操作--high);否则将high所指记录与枢轴记录交换
c.再从表的最左侧位置,依次向右搜索找到第一个关键字大于pivotkey的记录和枢轴记录交换。具体操作是:当low<high时,若low所指记录的关键字小于等于pivotkey,则向右移动指针low(执行操作++low);否则将low所指记录与枢轴记录交换
d.重复b和c,直至low和high相等为止。此时low和high的位置即为枢轴在此趟排序的最终位置,原表被分成两个子表
在上述过程中,记录的交换都是与枢轴之间发生,每次交换都要移动3次记录,可以先将枢轴记录暂存在r[0]的位置上,排序过程中只移动要与枢轴交换的记录,即只做r[low]或r[high]的单向移动,直至一趟排序结束后再将枢轴记录移至正确位置上
例:
起始:{3,4,5,1,2}
第一趟排序过程:
经过一趟排序后,确定了枢轴"3"的位置,同时分出[2,1]和[5,4]这两个子表,左子表均小于枢轴,右子表均大于枢轴,然后对左右子表进行递归操作即可
2.算法实现
1 using System.Collections.Generic; 2 3 public class TestQuickSort : TestSort 4 { 5 void Start() 6 { 7 List<int> list = new List<int> { 49, 38, 65, 97, 76, 13, 27, 49 }; 8 Print(list, "排序前:"); 9 QuickSort(list); 10 Print(list, "排序后:"); 11 } 12 13 //进行一趟排序,返回枢轴位置 14 int Partition(List<int> list, int low, int high) 15 { 16 int pivotkey = list[low];//用子表的第一个记录做枢轴记录 17 while (low < high)//从表的两端交替地向中间扫描 18 { 19 while (low < high && list[high] >= pivotkey) 20 { 21 high--; 22 } 23 list[low] = list[high];//将比枢轴记录小的移到低端 24 25 while (low < high && list[low] <= pivotkey) 26 { 27 low++; 28 } 29 list[high] = list[low];//将比枢轴记录大的移到低端 30 } 31 list[low] = pivotkey;//记录枢轴 32 return low; 33 } 34 35 void QSort(List<int> list, int low, int high) 36 { 37 if (low < high) 38 { 39 int pivotkeyPos = Partition(list, low, high);//将list一分为二,pivotkeyPos是枢轴位置 40 QSort(list, low, pivotkeyPos - 1);//对左子表递归排序 41 QSort(list, pivotkeyPos + 1, high);//对右子表递归排序 42 } 43 } 44 45 void QuickSort(List<int> list) 46 { 47 QSort(list, 0, list.Count - 1); 48 } 49 }
結果:
3.算法分析
a.时间复杂度
从快速排序算法的递归数可知,快速排序的趟数取决于递归树的深度
平均情况:O(nlog2n),优于冒泡排序的O(n2)
b.空间复杂度
快速排序是递归的,执行时需要有一个栈来存放相应的数据。最大递归调用次数与递归数的深度一致,所以最好情况下的空间复杂度为O(log2n),最坏情况下为O(n)
4.算法特点
a.是不稳定排序
b.当初始记录无序,n较大时,此算法宜采用