算法练习--快速排序堆排序

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 .... 再看一看。。。

 

以上是关于算法练习--快速排序堆排序的主要内容,如果未能解决你的问题,请参考以下文章

程序员必须掌握的十大排序算法(在线练习)

算法归并排序

直通BAT算法精讲附程序源码

常见排序算法的实现(归并排序快速排序堆排序选择排序插入排序希尔排序)

算法导论习题—堆排序快速排序

排序专题-插入排序