折腾算法之—快速排序交换次数
昨天在闪存上求到了这道算法题。
本学渣刚看到快速排序的时候一点印象都没有(辛苦培养我的高数老师,母校,祖国我对不起你们),于是百科了下快速排序的计算方法:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
好吧,虽然看起来有点复杂,但还是很好理解的。
百科还给出了各种语言的算法,PHP是这样的:
function quick($arr){ $size=count($arr); if($size>1){ $arr_1=array(); $arr_2=array(); for($i=1;$i<$size;$i++){ if($arr[$i]<$arr[0]){ $arr_1[]=$arr[$i]; } else{ $arr_2[]=$arr[$i];} } $arr_1=quick($arr_1) $arr_2=quick($arr_2); return array_merge($arr_1,array($arr[0]),$arr_2); } else{ return $arr; } } $arr=array(99,233,1,32,54,234,456,54,34,1); print_r(quick($arr));
但是这段代码却没有严格按照快速排序的思路来,而是讨巧的将数组第一个元素依次和后面的元素相比较,大的和小的分别放到不同数组里,和快速排序的比较交换位位置有所不同,这就体现出用计算机计算和人类计算不一样得地方了,不过他们的目的都是一样的:将小的和大的分开来,然后通过递归完成排序。
学渣表示这次脑洞开的有点大:
function quick($arr,&$count){ //参数前加&为引用形式,能够改变函数外的变量 $size=count($arr); $a=0; $b=$size-1;
if($size>1){ | $n=0; | while($a<$b){ | | $count_1=$count; | | for($i=$b;$i>$a;$i--){ //第一次查找交换 | | | if($arr[$a]>$arr[$i]){ | | | | $b=$i; | | | | $n=$b; | | | | $k=$arr[$a]; | | | | $arr[$a]=$arr[$i]; | | | | $arr[$b]=$k; | | | | $count++; | | | | break; | | | } | | } | | for($j=$a;$j<$b;$j++){ //第二次查找交换 | | | if($arr[$b]<$arr[$j]){ | | | | $a=$j; | | | | $n=$a; | | | | $k=$arr[$a]; | | | | $arr[$a]=$arr[$b]; | | | | $arr[$b]=$k; | | | | $count++; | | | | break; | | | } | | } | | if($count==$count_1){break;} //两次都没有交换说明此次循环完成 | } | | $arr_1=array_slice($arr,0,$n); | | $arr_1=quick_1($arr_1,$count); | | $arr_2=array_slice($arr,$n+1,$size-$n-1); | | $arr_2=quick_1($arr_2,$count);
| | return array_merge($arr_1,array($arr[$n]),$arr_2); }else{ | return $arr; } }
$count=0; //count用来统计交换次数
$arr=array(5,8,9,4,3);
$result=quick($arr,$count);
echo "count:".$count." resulte:";print_r($result);