算法练习--快速排序堆排序
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法练习--快速排序堆排序相关的知识,希望对你有一定的参考价值。
正题:
1、快速排序
原理:在初始序列中选择一个参考值,将序列其他数和该值进行对比,小的放一边大的放一边,然后把划分的两数组看成新序列,重新选择参考值,并比较划分。知道每个数组的元素个数为1停止。
代码:第一眼看上去,貌似递归的方式来弄比较好。
<?php
function Quick_sort(&$list , $start , $count) { if($start >= $count - 1) //设定终止条件。 { return; } $i = $start; $j = $count - 1; while($i != $j) { while($list[$i] <= $list[$j]) { if($i == $j) { break 2; } $j--; } $tmp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $tmp; while($list[$i] <= $list[$j]) { if($i == $j) { break 2; } $i++; } $tmp = $list[$i]; $list[$i] = $list[$j]; $list[$j] = $tmp; } Quick_sort($list , $start , $j); //对新序列进行排序 Quick_sort($list , $j+1 , $count); } //test for($i = 0 ; $i < 10; $i++) { $list[] = rand(2222,9999); } var_dump($list);echo "<br>";
//array(10) { [0]=> int(8807) [1]=> int(5257) [2]=> int(9920) [3]=> int(6181) [4]=> int(8825) [5]=> int(9654) [6]=> int(7439) [7]=> int(6529) [8]=> int(4514) [9]=> int(8810) }
Quick_sort($list , 0 , count($list)); var_dump($list);
//array(10) { [0]=> int(4514) [1]=> int(5257) [2]=> int(6181) [3]=> int(6529) [4]=> int(7439) [5]=> int(8807) [6]=> int(8810) [7]=> int(8825) [8]=> int(9654) [9]=> int(9920) } ?>
2、堆排序
原理:堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小 根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆 的要求可知,最大的值一定在堆顶。(摘于百度百科。。。)
说白了,这种排序基于特定的堆积树形式的排列特性。操作简略一点就是,将原序列变成大根堆,把首尾互换,去掉尾部(此时尾部就是最大,不用参与排序了),然后再变成大根堆,再首尾互换。。。直到序列就一个元素。
代码:这里面有个小问题,由于数组从0位开始,我也没去做处理。。。觉得没必要,主要算法思想最重要。因此里边很多 -1 的处理。有点乱。
<?php /** 节点筛运算,将根节点与子节点比较,如果小于子节点则调换值,且若子节点不为叶结点,那么对子节点也进行筛运算。 @param array 预改变的数组 @param int 根节点 @param int 最大节点 return ; */ function shift(&$list , $i , $max_count) { if($max_count <= 0) { return; } $node = floor($max_count/2); if(($list[$i-1] < $list[$i*2-1]) || ($i*2 <= $max_count && $list[$i-1] < $list[$i*2])) { $change = ($i*2 <= $max_count) && ($list[$i*2-1] < $list[$i*2]) ? $i*2 : $i*2-1; $tmp = $list[$i-1]; $list[$i-1] = $list[$change]; $list[$change] =$tmp; if($i*2 <= $node) { shift($list , $i*2 , $max_count); } if($i*2+1 <= $node) { shift($list , $i*2+1 , $max_count); } } return ; } function Heap_sort($list) { $node = floor(count($list)/2); for($j = $node ; $j>0 ; $j--) { shift($list , $j , count($list)-1); } for($number = count($list); $number > 1;) { $tmp = $list[0]; $list[0] = $list[$number-1]; $list[$number-1] = $tmp; $number--; $node = floor($number/2); for($j = $node ; $j>0 ; $j--) { shift($list , $j , $number-1); } } return $list; } //test $list = array(36,25,48,12,65,43,20,58); $list = Heap_sort($list); print_r($list); //Array ( [0] => 12 [1] => 20 [2] => 25 [3] => 36 [4] => 43 [5] => 48 [6] => 58 [7] => 65 ) ?>
自我感觉堆排序的想法还是挺精妙的。时间复杂情况不会有什么变化,不论序列如何,筛运算该做什么就做什么。这里筛运算我用的递归,感觉不是特别妥当,看了看书上的,直接使用循环做的,没有太看懂 orz .... 再看一看。。。
以上是关于算法练习--快速排序堆排序的主要内容,如果未能解决你的问题,请参考以下文章