终于讲到了排序的重点了。快排即使不是排序中最经典的算法,能算上是非常出色的算法了 快速排序是一种基于分治技术的重要排序算法,是冒泡算法的一种改进。是由东尼.霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要O(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。 快速排序用分治的思想,将一个整串分为两个子串。左边子串中所有的数都不会大于右边子串中的数。 步骤为: 递归的最底层是零个或者一个数,也就说是已经排好序的。 我看了网上很多的数学证明,也不想多说。再说,即使用数学证明出来了,实际应用也是另一回事。我到现在也就知道快排的最好、平均和最坏的时间复杂度,而没有去纠结是怎么证明出来的(或许这样不好吧)。最好:O(nlogn), 平均:O(1.38nlogn,也就是nlogn),最坏:O(n2)。平均情况下只比最好情况多执行38%的比较操作,不过最坏情况下就已经是平方的数量级了。 被快速排序所使用的空间,依照使用的版本而定。使用原地(in-place)分区的快速排序版本,在任何递归调用前,仅会使用固定的額外空間。然而,如果需要产生O(logn)嵌套递归调用,它需要在他们每一个存储一个固定数量的信息。因为最好的情况最多需要O(log n)次的嵌套递归调用,所以它需要O(log n)的空间。最坏情况下需要O(n)次嵌套递归调用,因此需要O(n)的空间。 然而我们在这里省略一些小的细节。如果我们考虑排序任意很长的数列,我们必须要记住我们的变量像是left和right,不再被认为是占据固定的空间;也需要O(log n)对原来一个n项的数列作索引。因为我们在每一个堆栈框架中都有像这些的变量,实际上快速排序在最好跟平均的情况下,需要O(log2 n)空间的比特数,以及最坏情况下O(n log n)的空间。然而,这并不会太可怕,因为如果一个数列大部份都是不同的元素,那么数列本身也会占据O(n log n)的空间字节。 非原地版本的快速排序,在它的任何递归调用前需要使用O(n)空间。在最好的情况下,它的空间仍然限制在O(n),因为递归的每一阶中,使用与上一次所使用最多空间的一半,且 具体算法如下: 快排的算法很简单,而且大部分高级语言的排序库函数都是用的快排。不过我们从快排的这个分治思想中还是能够学到很多的东西的。 好的,快排就先这样吧。1. 快排简介 #
2. 快排原理 #
3. 时间和空间复杂度 #
2n
。它的最坏情况是很恐怖的,需要O(n2)
空间,远比数列本身还多。如果这些数列元素本身自己不是固定的大小,这个问题会变得更大;举例来说,如果数列元素的大部份都是不同的,每一个将会需要大约O(logn)为原来存储,导致最好情况是O(n log n)和最坏情况是O(n2 log n)的空间需求。4. 算法 #
//交换两个数
function swap(&$x, &$y){
$temp = $x;
$x = $y;
$y = $temp;
}
function partition(&$a, $left, $right){
$p = $a[$left];
$i = $left;
$j = $right+1;
do{
//寻找大数
do{
$i++;
}while($a[$i]<$p && $i<=$j);
//寻找小数
do{
$j--;
}while($a[$j]>$p && $j>=$i);
//交换
swap($a[$i], $a[$j]);
}while($i<$j);
swap($a[$i], $a[$j]);
swap($a[$left], $a[$j]);
return $j;
}
//快排,数组,左边界,右边界(数组长度)
function quickSort(&$a, $left, $right){
if($left>=$right){
return;
}
$mid = partition($a, $left, $right);
quickSort($a, $left, $mid);
quickSort($a, $mid+1, $right);
}
5. 快排思想 #
版权属于:
加速器之家
作品采用:
《
署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)
》许可协议授权
评论