快速排序法
快速排序采用的思想是分治思想。
快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置。递归快速排序,将其他n-1个元素也调整到排序后的正确位置。最后每个元素都是在排序后的正确位置,排序完成。所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归。
举例说明一下吧,这个可能不是太好理解。假设要排序的序列为
2 2 4 9 3 6 7 1 5 首先用2当作基准,使用i j两个指针分别从两边进行扫描,把比2小的元素和比2大的元素分开。首先比较2和5,5比2大,j左移
2 2 4 9 3 6 7 1 5 比较2和1,1小于2,所以把1放在2的位置
2 1 4 9 3 6 7 1 5 比较2和4,4大于2,因此将4移动到后面
2 1 4 9 3 6 7 4 5 比较2和7,2和6,2和3,2和9,全部大于2,满足条件,因此不变
经过第一轮的快速排序,元素变为下面的样子
[1] 2 [4 9 3 6 7 5]
之后,在把2左边的元素进行快排,由于只有一个元素,因此快排结束。右边进行快排,递归进行,最终生成最后的结果
比轴值小的放它的左边,比轴值大的放它的右边,这样最后找的的下标(low==high)就是当前轴值应该在的位置。
每个元素都要当一次轴值
核心代码:
int Partition(int *array, int left, int right) { if (left < right) //递归结束的条件 left==right { int index = array[left]; int low = left; int high = right; while (low < high) { //从右向左找比轴值小的,找到就放在开始位置 while (low<high && array[high] >= index) high--; array[low] = array[high]; //从左向右找比轴值大的,找到就放在末尾 while (low<high && array[low] <= index) low++; array[high] = array[low]; } array[low] = index; //轴值放在它应该在的位置 Partition(array, left, low - 1); //对低子表递归排序 Partition(array, low + 1, right); //对高子表递归排序 } return 0; }
void QuickSort(int array[], int len) { Partition(array, 0, len - 1); }
完整的代码:
#include <stdio.h> #include <stdlib.h> int Partition(int *array, int left, int right) { if (left < right) //递归结束的条件 left==right { int index = array[left]; int low = left; int high = right; while (low < high) { //从右向左找比轴值小的,放在开始位置 while (low<high && array[high] >= index) high--; array[low] = array[high]; //从左向右找比轴值大的,放在末尾 while (low<high && array[low] <= index) low++; array[high] = array[low]; } array[low] = index; Partition(array, left, low - 1); //对低子表递归排序 Partition(array, low + 1, right); //对高子表递归排序 } return 0; } void QuickSort(int array[], int len) { Partition(array, 0, len - 1); } void main() { int a[] = { 1, 5, 2, 4, 2 }; int len = sizeof(a) / sizeof(a[0]); QuickSort(a, len); for (int i = 0; i<len; i++) printf("%d\n", a[i]); system("pause"); }
最坏时间复杂度为 O(n²),平均时间复杂度为O(nlogn)。
空间复杂度,需要一个栈空间来实现递归。空间复杂度为O(logn).
基准关键字的的选择
基准关键字的选择决定了快速排序算法性能的关键。常用的有一下几种方式:
1.三数取中
对左端、右端和中间的三个值进行排序,选取中值作为基准关键字。
2.取随机数
取一个随机数 m(left <=m<= right),以array[m]作为基准关键字。
需要注意快速排序和归并排序的联系和区别:
联系:它们都是基于分治思想的,分组排序。递归实现。
区别:归并排序,是不断的折半分,然后在合并在辅助数组中排序。
快速排序,根据基准值进行分组,分完之后,基准值的位置就是排序后的位置。

浙公网安备 33010602011771号