快速排序算法
1、简介
- 可以认为是性能最好的排序方法,数据规模越大快速排序的性能越优
- 核心思想是分治
2、算法思路
Partition 划分
- 快速排序中最重要的一个步骤是划分
- 在待排续表L[1,...,n]中任取一个元素
pivot
作为基准,给基准数据找其正确索引位置 - 划分后左边的元素都比
pivot
小,右边的元素都比pivot
大,于是形成了两个子序列 - 每一次划分能确定
pivot
在序列中的位置
划分实现思路
- 找到
pivot
PS: 这里有很多可以优化的地方,重要的是pivot
不要选成最小的 - 初始化low为划分部分第一个元素的位置,high为最后一个元素的位置
high
向前移动找到第一个比pivot
小的元素,这里的先后顺序不能乱(根据pivot
所在位置)- low向后移动找到第一个比
pivot
大的元素 - 交换当前两个位置的元素
- 继续234的过程直到
low>=high
为止 - 此时
low == high
就是pivot
应该在的位置
3、代码实现
-
RandomInRange
用于在序列中随机获取pivot
,主要是应对一种极端情况(算法分析部分会讲)//随机选择Pivot的位置 int RandomInRange(int low, int high) { return rand() % (high - low + 1) + low; } //将子序列按照Pivot划分为两个子序列 template<class T> int Partition(T* array, int low, int high) { //得到Pivot int index = RandomInRange(low, high); T pivot = array[index]; //将Pivot移到子序列的首位,统一操作 array[index] = array[low]; array[low] = pivot; while (low < high) { while (low < high && pivot <= array[high]) high--; //从high开始向右找到第一个小于pivot的值 array[low] = array[high]; while (low < high && pivot >= array[low]) low++; //从low开始向左找到第一个大于pivot的值 array[high] = array[low]; } array[low] = pivot; //此时high == low的位置就是pivot的位置 return low; //返回两个子序列的分界点 } //快速排序 template<class T> void QuickSort(T* array, int low, int high) { if (low < high) { //如果子序列长度不为1 int index = Partition(array, low, high);//进行一次划分 //对pivot左右两个序列继续进行快速排序 QuickSort(array, low, index-1); QuickSort(array, index +1, high); } }
4、算法分析
- 空间复杂度 :
O(logn)
- 时间复杂度:
O(n*logn)
- 最坏复杂度
O(n^2)
,待排序序列本身就是一个有序的序列,或者说每次划分选取的pivot
总是当前切分数组的最小值(这就是随机选取pivot
的意义,也有其他的方法) - 不稳定:交换过程中可能会改变先后顺序
改进思路:
- 选取
pivot
的方法 - 先判断数组的大小,如果小于某个值的时候,就用插入排序,大于某个值就用快速排序