看了C语言版本的快速排序后,我用PHP实现了一遍。
难度在于在一个数组上面进行位置的交换理解
算法
一列很长很长很长的队伍,我要排序,先抽一个队长,然后以队长为准,比队长高的排队长右边,比队长矮的排队长左边。 然后以队长为中界分成两个小分队。 各小分队又抽一个小队长 这个小队长又按照大队长的做法做了一遍……..
此图来源互联网:
具体过程
- 乱数组中,取第一个数进行参考值。(这个数随你喜欢,在数组中任意一个就可以了。但为了方便,取第一个位置)
- 取第一个位置的数值用$key变量临时保存起来。
- 分别再用$i ,$j 变量保存起数值的开始和结束位置。($start,$end是固定的位置,下面用到的是变动的位置)
- 从右边开始循环寻找,比$key小的数值赋值到$i位置(也就是$key的原本的位置,那个比$key小的位置变成的脏值),如果不符合条件的每找一个位置$j递减。
- 从左边开始循环寻找,比$key大的数值或等于$key的赋值到那个比$key小的位置,如果不符合条件的每找一个位置$i递增。(这相当两个参考于$key的大小值,进行了对换,那如果这乱的数组只有3个数值的时候,那不相当于排序?当然现在 那个比$key大的位置也变成的脏值,继续像第四步那样重复做一遍。)
- 当循环的位置$i,$j靠近(有些老师说是中间位置,其实是不对的,应该说两位置靠近。)的时候,还剩一个含有脏值的$i位置,就把$\key赋值到\$i位置。为什么要赋值到\$i位置?看列表下面解析。
- 大小数值由$key做参考分成了两边,即使是两边,但两边还是乱的,再把这两边的数列递归。(像从第一步开始重做一遍)
- 一直递归这样的操作,直到开始位置大于或等于结束位置,数组就排序完了。
问题:两边位置缩小成 左边位置无法大于右边位置时,也就是相邻的两个位置,那为什么$key最终用左边$i的位置?
答案:因为那个位置,从一开始就是$key的让出来的位置,所以最后没人认领的位置应该留给$key,这样数组才不多不少。
代码实现
<?php
$testArray = array();
for ($i=0; $i < 100; $i++) {
$testArray[] = rand(1, 100);
}
echo '<pre>';
print_r($testArray);
echo '</pre>';
recursive(0, 99);
echo '<pre>';
print_r($testArray);
echo '</pre>';
function recursive($start, $end) {
global $testArray;
if ( $end <= $start ) {
return;
}
$i = $start;
$j = $end;
$key = $testArray[$start];
while( $j > $i ) {
while( $j > $i && $key < $testArray[$j] ) {
$j--;
}
$testArray[$i] = $testArray[$j];
while( $j > $i && $key >= $testArray[$i] ) {
$i++;
}
$testArray[$j] = $testArray[$i];
}
$testArray[$i] = $key;
recursive($start, $i-1);
recursive($i+1, $end);
}