快速排序是一种常用的内部排序算法,平均时间复杂度为
O(nlogn)
。
算法思路
快速排序使用分治法来把一个序列分为较小和较大的两个子序列,然后递归地排序两个子序列。步骤如下:
- 挑选基准值: 从序列中选择任意一个元素作为基准,通常选择序列的第一个元素。
- 分割序列: 将序列中比基准元素小的元素放到基准前面,大的放在基准后面。
- 递归排序: 对较小的和较大的子序列分别进行上述操作。
举例说明
例如对序列 [ 3, 5, 4, 1, 2, 6 ]
进行快速排序
-
选取元素
3
作为基准元素。 -
将比
3
小的元素放在3
前面,大的放在3
后面,将其分割成两个子序列。 -
重复上述两个步骤,直到子序列划分完毕。
划分序列
序列划分有两种常用的方式。
方法一
从左到右遍历并调整交换位置,用offset记录偏移的量,用于填充基准元素。
-
初始化
offset
基准元素后的第一个位置 ( 即offset = low + 1
),从offset位置开始往后扫描,找到比3
小的元素1
,交换1
和基准外第一个位置的元素5
,交换后offset
自增。 -
找到比
3
小的元素2
,交换2
和基准外第二个位置的元素4
,交换后offset
自增。 -
将基准元素与 offset - 1 位置处元素交换位置,既可将序列划分成两部分。
方法二
从两端向中间遍历,用变量缓存基准元素。
-
将序列第一个元素
2
当做基准元素,定义pivot
变量缓存基准元素的值,并使low
和high
分别赋值为第一个元素和最后一个元素的索引。 -
从后往前找到第一个比基准元素小的元素
2
,将其赋值给s[low]
。 -
从前往前后到第一个比基准元素大的元素
5
,将其赋值给s[high]
。 -
从后往前找到第一个比基准元素小的元素
1
,将其赋值给s[low]
。 -
从前往前后到第一个比基准元素大的元素
4
,将其赋值给s[high]
。 -
到达终止条件,将
pivot
赋值给s[low]
,即可将序列划分成两部分。
具体实现
分割序列,递归划分子序列
|
|
方法一
第一种分割方式实现
|
|
方法二
第二种分割方式实现
|
|
单元测试
|
|