【算法】PHP实现经典算法(下)

前言

前几天,我们通过PHP实现了不同的排序算法,并比较算法对应的耗时。
【算法】PHP实现经典算法(上)

下面我们来实现下列算法

  • 堆排序
  • 鸡尾酒排序
  • 直接选择排序
  • 计数排序

CODE


$arr = [];

for ($i = 0; $i < 5000; $i++) {
    $arr[] = rand(1, 50000);
}

// 5 堆排序

/**
 * 交换两个数的位置
 * @param $a
 * @param $b
 */
function swap(&$a,&$b){
    $temp = $b;
    $b = $a;
    $a = $temp;
}

/**
 * 左子树
 * @param $i
 * @return mixed
 */
function lchild($i){ return $i*2+1;}

/**
 * 右子树
 * @param $i
 * @return mixed
 */
function rchild($i){ return $i*2+2;}

/**
 * 整理节点
 * @param $array 待调整的堆数组
 * @param $i 待调整的数组元素的位置
 * @param $heapsize  数组的长度
 */
function build_heap(&$array,$i,$heapsize){

    $left = lchild($i);
    $right = rchild($i);
    $max = $i;
    //如果比左子树小并且在左右子树的右面,边界调整到左侧
    if($i < $heapsize && $left < $heapsize  && $array[$left] > $array[$i] ){
        $max = $left;
    }

    //如果比右子树小并且都小于要构建的数组长度,边界调整到右侧
    if($i < $heapsize && $right < $heapsize && $array[$right] > $array[$max]){
        $max = $right;
    }

    //如果经过两次调整后,要调整的数组不是最大值
    if($i != $max && $i < $heapsize && $max < $heapsize){

        //就交换对应的位置,并再次进行整理节点
        swap($array[$i],$array[$max]);
        build_heap($array,$max,$heapsize);

    }
}

/**
 * 对堆进行排序
 * @param $array 要排序的数组
 * @param $heapsize 数组的长度
 */
function sortHeap(&$array,$heapsize){
    while($heapsize){ //长度逐步递减0

        //首先交换第一个元素和最后一个元素的位置
        swap($array[0],$array[$heapsize-1]);
        $heapsize = $heapsize -1;
        build_heap($array,0,$heapsize); //整理数组的第一个的元素的位置,长度为逐步递减的数组长度
    }
}

/**
 * 创建堆
 * @param $array
 * @param $heapsize
 */
function createHeap(&$array,$heapsize){
    $i = ceil($heapsize/2)-1; //找到中间的位置
    for( ; $i>=0 ;$i-- ){  //从中间往前面整理堆
        build_heap($array,$i,$heapsize);
    }
}

/**
 * 堆排序主函数
 */
function Heapsort($array){
    $heapsize = count($array);
    createHeap($array,$heapsize);
    sortHeap($array,$heapsize);

    return $array;

}

$heapsort_start_time = microtime(true);

$heapsort_sort = Heapsort($arr);

$heapsort_end_time = microtime(true);

$heapsort_need_time = $heapsort_end_time - $heapsort_start_time;

print_r("堆排序耗时:" . $heapsort_need_time . "<br />");

// 6 鸡尾酒排序法

/**
 * 鸡尾酒排序
 * @param $arr
 * @return mixed
 */
function Cocktailsort($arr) {
    $arr_len  =count($arr);

    for($i = 0 ; $i < ($arr_len/2) ; $i ++){
        //将最小值排到队尾
        for( $j = $i ; $j < ( $arr_len - $i - 1 ) ; $j ++ ){
            if($arr[$j] < $arr[$j + 1] ){
                swap($arr[$j],$arr[$j + 1]);
            }
        }
        //将最大值排到队头
        for($j = $arr_len - 1 - ($i + 1); $j > $i ; $j --){
            if($arr[$j] > $arr[$j - 1]){
                swap($arr[$j],$arr[$j - 1]);
            }
        }
    }
    return $arr;
}

$cocktailsort_start_time = microtime(true);

$cocktailsort_sort = Cocktailsort($arr);

$cocktailsortt_end_time = microtime(true);

$cocktailsort_need_time = $cocktailsortt_end_time - $cocktailsort_start_time;

print_r("鸡尾酒排序耗时:" . $cocktailsort_need_time . "<br />");

// 7  希尔排序

/**
 * 希尔排序
 * @param $arr
 */
function Shellsort($arr)
{
    $n=count($arr); //数组长度

    for($gap=floor($n/2);$gap>0;$gap=floor($gap/=2)) //
    {
        for($i=$gap;$i<$n;++$i) //根据增量循环
        {
            //以增量为步幅进行查看
            for( $j=$i-$gap; $j>=0 && $arr[$j+$gap] < $arr[$j]; $j -= $gap)
            {
                swap($arr[$j],$arr[$j+$gap]);
            }
        }
    }

    return $arr;
}

$shellsort_start_time = microtime(true);

$shellsort_sort = Cocktailsort($arr);

$shellsort_end_time = microtime(true);

$shellsort_need_time = $shellsort_end_time - $shellsort_start_time;

print_r("希尔排序耗时:" . $shellsort_need_time . "<br />");

// 8  直接选择排序

/**
 * 直接选择排序
 * @param $arr
 * @return mixed
 */
function  Straightselectsort($arr){

    $n = count($arr);

    for($i = 0 ; $i < $n - 1;$i++){
        $m = $i;
        for($j = $i+1 ; $j < $n; $j++){
            if($arr[$j] < $arr[$m] ){
                $m = $j;
            }

            if($m != $j){
                //进行交换
                swap($arr[$m],$arr[$j]);
            }
        }
    }
    return $arr;
}

$straightselectsort_start_time = microtime(true);

$straightselectsort_sort = Cocktailsort($arr);

$straightselectsort_end_time = microtime(true);

$straightselectsort_need_time = $straightselectsort_end_time - $straightselectsort_start_time;

print_r("直接选择排序耗时:" . $straightselectsort_need_time . "<br />");

// 9  计数排序

/**
 * 计数排序
 * @param $arr
 * @return mixed
 */
function Countsort($arr){

    $max = $arr[0];
    $min = $arr[0];

    foreach($arr as $key => $value) {
        if ($value > $max) {
            $max = $value;
        }
        if ($value < $min) {
            $min = $value;
        }
    }
        //这里k的大小是要排序的数组中,元素大小的极值差+1
        $c=[];
        $k = $max - $min + 1;
        for($i = 0; $i < count($arr) ; $i ++){
            $c[$arr[$i] - $min ] +=1;
        }

        for($i=1;$i < count($c); ++$i){
            $c[$i] = $c[$i] + $c[$i - 1];
        }

        for($i = count($arr);$i > 0 ; --$i){
            $b[ -- $c[$arr[$i] - $min] ] = $arr[$i];
        }

    return $b;
}

$countsort_start_time = microtime(true);

$countsort_sort = Cocktailsort($arr);

$countsort_end_time = microtime(true);

$countsort_need_time = $countsort_end_time - $countsort_start_time;

print_r("计数排序耗时:" . $countsort_need_time . "<br />");

耗时对比

堆排序耗时:0.086709976196289
鸡尾酒排序耗时:4.6467659473419
希尔排序耗时:4.4215688705444
直接选择排序耗时:4.529422044754
计数排序耗时:4.2601070404053

参考资料

  • 算法导论
时间: 2024-11-03 22:19:10

【算法】PHP实现经典算法(下)的相关文章

php排序算法?php排序经典算法

 代码如下 复制代码 1.冒泡算法,排序算法,由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序 $array = array(a,f,c,b,e,h,j,i,g);     function maopao_fun($array){         if($len <= 1) {             return $arr;         }         $count = count($array);         for($i=0;$i<$count;

数据结构经典算法

C#选择排序 using System:namespace SelectionSorter{ public class SelectionSorter{ private int min:public void Sort(int [] list){ for(int i=0:i<list.Length-1:i++){ min=i:for(int j=i+1:j<list.Length:j++){ if(list[j]<list[min])min=j:}int t=list[min]:list

php经典算法集锦_php技巧

本文实例讲述了php几个经典算法.分享给大家供大家参考,具体如下: 有5个人偷了一堆苹果,准备在第二天分赃.晚上,有一人遛出来,把所有菜果分成5份,但是多了一个,顺手把这个扔给树上的猴了,自己先拿1/5藏了.没想到其他四人也都是这么想的,都如第一个人一样分成5份把多的那一个扔给了猴,偷走了1/5.第二天,大家分赃,也是分成5份多一个扔给猴了.最后一人分了一份.问:共有多少苹果? for ($i = 1; ; $i++) { if ($i%5 == 1) { //第一个人取五分之一,还剩$t $t

数据挖掘十大经典算法(详解)

数据挖掘十大经典算法  一. C4.5  C4.5算法是机器学习算法中的一种分类决策树算法,其核心算法是ID3 算法.   C4.5算法继承了ID3算法的优点,并在以下几方面对ID3算法进行了改进:  1) 用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足:  2) 在树构造过程中进行剪枝:  3) 能够完成对连续属性的离散化处理:  4) 能够对不完整数据进行处理.  C4.5算法有如下优点:产生的分类规则易于理解,准确率较高.其缺点是:在构造树的过程中,需要对数据

经典算法(12) 数组中只出现1次的两个数字(百度面试题)

首先来看题目要求: 在一个数组中除两个数字只出现1次外,其它数字都出现了2次, 要求尽快找 出这两个数字. 考虑下这个题目的简化版--数组中除一个数字只出现1次外,其它数字都成对出现 ,要求尽快找出这个数字.这个题目在之前的<位操作基础篇之位操作全面总结>中的"位操作趣味应用" 中就已经给出解答了.根据异或运算的特点,直接异或一次就可以找出这个数字. 现在数组中有两个 数字只出现1次,直接异或一次只能得到这两个数字的异或结果,但光从这个结果肯定无法得到这个两个数字 .因此我

经典算法(8) MoreWindows白话经典算法之七大排序总结篇

在我的博客对冒泡排序,直接插入排序,直接选择排序,希尔排序,归并排序,快速排序和堆排序这七种 常用的排序方法进行了详细的讲解,并做成了电子书以供大家下载.下载地址为: http://download.csdn.net/detail/morewindows/4443208. 有网友提议到 这本<MoreWindows白话经典算法之七大排序>电子书讲解细致用来平时学习是非常好的,但是页数有22页, 不太合适做面试前的复习资料.因此在这里将这七种常用的排序方法进行下总结,以便大家更好的复习这些 经典

经典算法(3) 希尔排序的实现

希尔排序的实质就是分组插入排序,该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成 的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小) 时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况), 效率是很高的,因此希尔排序在时间效率上比前两种方法有较大提高. 以n=10的一个数组49, 38, 65,

JavaScript中数据结构与算法(五):经典KMP算法

  这篇文章主要介绍了JavaScript中数据结构与算法(五):经典KMP算法,本文详解了KMP算法的方方面在,需要的朋友可以参考下 KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配是指:模式串和母串的的比较从右到左,模式串的移动从左到右. 通过上一章显而易见BF算法也是属于前缀的算法,不过就非常霸蛮的逐个匹配的效率自然不用提了O(mn),网上

PHP经典算法集锦【经典收藏】_php技巧

本文实例总结了PHP经典算法.分享给大家供大家参考,具体如下: 1.首先来画个菱形玩玩,很多人学C时在书上都画过,咱们用PHP画下,画了一半. 思路:多少行for一次,然后在里面空格和星号for一次. <?php for($i=0;$i<=3;$i++){ echo str_repeat(" ",3-$i); echo str_repeat("*",$i*2+1); echo '<br/>'; } 2.冒泡排序,C里基础算法,从小到大对一组数