快速排序利用分治思想:
- 确定分界点
x;- 可取左边界
l、右边界r、中间点,也可以随机取。 x点指向的数叫作 pivot。
- 可取左边界
- 用
x将原先区间划分为两个区间,左区间的值都<= x,右区间的值都>= x;- 指针
pl先开始从左往右移动; pl移动到>= x的数停住;- 必须要有
=
- 必须要有
- 指针
pr开始从右往左移动; pr移动到<= x的数停住;- 必须要有
=
- 必须要有
- 交换
pl和pr指向的两个数; pl和pr继续按照这一规则移动;- 终止条件是
pl >= pr(双指针交汇),这时pl左边的数都<= x,pr右边的数都>= x。- 每一步操作后都满足
pr右边的数>= x,双指针交汇后pl也就没必要继续右移去做检查;同理pr也无需继续左移。
- 每一步操作后都满足
- 指针
- 继续递归处理左右两个区间。
- 递归终止条件是
l >= r,意味着区间里没有数或只有一个数。 - 递归终止条件满足时,排序已完成。
- 递归终止条件是
| |
边界点分析:
- 原区间包含两个数
[1, 2],递归区间就是[l, pr]对应[pr+1, r],此时pivot不能取到右边界r,pivot = nums[(l+r)/2];- 若取到右边界 1(
(l+r+1)/2 == 1),此时pivot == 2; - 初始时,
l == 0,r == 1; - 第一次递归前,
pl == 1,pr未移动,pr == 1(不满足pl < pr,两个数无需交换); - 接着进行递归,
qs(nums, 0, 1)导致了死循环,而qs(nums, 2, 1)没有问题。
- 若取到右边界 1(
- 原区间包含两个数
[1, 2],递归区间就是[l, pl-1]对应[pl, r],此时pivot不能取到左边界r,pivot = nums[(l+r+1)/2]。- 若取到左边界 0(
(l+r)/2 == 0),此时pivot == 1; - 初始时,
l == 0,r == 1; - 第一次递归前,
pl未移动,pl == 0,pr == 0(不满足pl < pr,两个数无需交换); - 接着进行递归,
qs(nums, 0, -1)没问题,而qs(nums, 0, 1)就导致了死循环。
- 若取到左边界 0(
快速选择算法(第 k 个数)利用快速排序算法的思想,每次只需要选半边递归。
| |
References