排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)

快速排序

参考文章:快速排序


快速排序(英语:Quicksort)
又称划分交换排序(partition-exchange sort)。



图示为使用快速排序对一列数字排序的过程。

排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)_第1张图片
事实上,快速排序通常明显比其他O(nlog2n)算法更快。因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

复杂度和具体元素交换步骤如下

排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)_第2张图片




右图的交换步骤可能不是很清晰,可直接参照下面的java实现理解。
排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)_第3张图片

快速排序使用分治法策略来把一个序列分为两个子序列。算法步骤如下: 1. 选取“基准”:从数列中挑出一个元素,称为"基准"(pivot) 2. 分区(partition):重新排序数列,**所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)**。在这个分区结束之后,该基准就处于数列的中间位置。 3. 递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。 递归到最底部时,数列的大小是零或一,也就是已经排序好了。

这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。(最终排好序时其应该在的位置)

java实现

思路为选取当前数组中间数字为“基准”;

  1. 用两个遍历从“基准”前(头)和后(尾)分别往后(前)遍历;
  2. 当头和尾“遇到一起”或头在尾之后,此次遍历结束;
  3. 当头往后遍历到一个元素,尾往前遍历到一个元素,且者两个元素满足:头指向的元素不小于“基准”,尾指向的元素不大于“基准”时先将这两个元素交换,后头继续往后移动一位,尾继续往前移动一位,继续该次循环;
  4. 没找到则继续遍历;

排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)_第4张图片

上图为一次排序过程:
有大小为9的数组{1,8,9,4,3,4,3,2,1}

  • h0t8表示初始时头(head)指向下标0处,尾(tail)指向下标8处,“基准”为3(用 .3. 表示);

  • 之后头和尾按上述思路3开始遍历,遍历到i1j8处(i为头,j为尾),此时满足条件,交换元素1和8,移动头尾,继续循环;

  • 接下来到了i2j7处,满足上述3,指向操作(交换9和2),此时数组为:1,1,2,4,3,4,3,9,8

  • 继续循环经过i3j6,i4k5后到了i5j5,头尾遍历到了“基准”处,此次循环结束

排序:五. 快速排序(将“基准”前,后不符合规则的元素交换)_第5张图片

取中间位置元素为“基准”;
取“基准”以左最左元素为“头”;
取“基准”以右最右元素为“尾”;
从两端向中间遍历;
找到“头”往后第一个不小于“基准”的元素a及其下标i;
找到“尾”往前第一个不大于“基准”的元素b及其下标j;
如果i < j,交换a和b,继续循环;
如果i==j,此次排序结束,开始下一次递归;
如果i > j,结束循环,此次排序结束,开始下一次递归;

代码已上传 GitHub,可以在 这里 找到

你可能感兴趣的:(算法)