php 排序算法

2 篇文章 0 订阅

冒泡排序
排序 n 个项目要Ο(n²)次比较,在最坏状况下则需要Ο(n²)次比较

function maopao($arr)
{
$len = count($arr);
//从小到大
for($i=1;$i<$len;$i++)
{
for($j=$len-1;$j>=$i;$j--)
if($arr[$j]<$arr[$j-1])
{//如果是从大到小的话,只要在这里的判断改成if($arr[$j]>$arr[$j-1])就可以了
 $tmp=$arr[$j];
 $arr[$j]=$arr[$j-1];
 $arr[$j-1]=$tmp;
}
}
$arr=array('3','8','1','4','11','7');
print_r(maopao($arr));

快速排序
排序 n 个项目要Ο(n log n)次比较,在最坏状况下则需要Ο(n2)次比较

// 快速排序
function kuaisu($arr){
    $len = count($arr);
    if($len <= 1){
        return $arr;
    }
    $key = $arr[0];
    $left_arr = array();
    $right_arr = array();
    for($i=1; $i<$len;$i++){
        if($arr[$i] <= $key){
            $left_arr[] = $arr[$i];
        }else{
            $right_arr[] = $arr[$i];
        }
    }
    $left_arr = kuaisu($left_arr);
    $right_arr = kuaisu($right_arr);
    return array_merge($left_arr, array($key), $right_arr);
}
$arr = array(23,98,54,2,9,62,34);
print_r(kuaisu($arr));

堆排序

//因为是数组,下标从0开始,所以,下标为n根结点的左子结点为2n+1,右子结点为2n+2;  
//初始化值,建立初始堆
$arr=array(49,38,65,97,76,13,27,50);
$arrSize=count($arr);

//将第一次排序抽出来,因为最后一次排序不需要再交换值了。
buildHeap($arr,$arrSize);

for($i=$arrSize-1;$i>0;$i--){
    swap($arr,$i,0);
    $arrSize--;
    buildHeap($arr,$arrSize);   
}

//用数组建立最小堆
function buildHeap(&$arr,$arrSize){
    //计算出最开始的下标$index,如图,为数字"97"所在位置,比较每一个子树的父结点和子结点,将最小值存入父结点中
    //从$index处对一个树进行循环比较,形成最小堆
    for($index=intval($arrSize/2)-1; $index>=0; $index--){
        //如果有左节点,将其下标存进最小值$min
        if($index*2+1<$arrSize){
            $min=$index*2+1;
            //如果有右子结点,比较左右结点的大小,如果右子结点更小,将其结点的下标记录进最小值$min
            if($index*2+2<$arrSize){
                if($arr[$index*2+2]<$arr[$min]){
                    $min=$index*2+2;
                }
            }
            //将子结点中较小的和父结点比较,若子结点较小,与父结点交换位置,同时更新较小
            if($arr[$min]<$arr[$index]){
                swap($arr,$min,$index);
            }   
        }
    }
}

//此函数用来交换下数组$arr中下标为$one和$another的数据
function swap(&$arr,$one,$another){
    $tmp=$arr[$one];
    $arr[$one]=$arr[$another];
    $arr[$another]=$tmp;
}

归并排序

//merge函数将指定的两个有序数组(arr1arr2,)合并并且排序
//我们可以找到第三个数组,然后依次从两个数组的开始取数据哪个数据小就先取哪个的,然后删除掉刚刚取过///的数据
function al_merge($arrA,$arrB)
{
    $arrC = array();
    while(count($arrA) && count($arrB)){
        //这里不断的判断哪个值小,就将小的值给到arrC,但是到最后肯定要剩下几个值,
        //不是剩下arrA里面的就是剩下arrB里面的而且这几个有序的值,肯定比arrC里面所有的值都大所以使用
        $arrC[] = $arrA['0'] < $arrB['0'] ? array_shift($arrA) : array_shift($arrB);
    }
    return array_merge($arrC, $arrA, $arrB);
}
//归并排序主程序
function al_merge_sort($arr){
    $len=count($arr);
    if($len <= 1)
        return $arr;//递归结束条件,到达这步的时候,数组就只剩下一个元素了,也就是分离了数组
    $mid = intval($len/2);//取数组中间
    $left_arr = array_slice($arr, 0, $mid);//拆分数组0-mid这部分给左边left_arr
    $right_arr = array_slice($arr, $mid);//拆分数组mid-末尾这部分给右边right_arr
    $left_arr = al_merge_sort($left_arr);//左边拆分完后开始递归合并往上走
    $right_arr = al_merge_sort($right_arr);//右边拆分完毕开始递归往上走
    $arr=al_merge($left_arr, $right_arr);//合并两个数组,继续递归
    return $arr;
}
foreach(al_merge_sort($arr) as $val)
{
    echo $val."<br>";
}

这里写图片描述

归并排序和堆排序、快速排序的比较

若从空间复杂度来考虑:首选堆排序,其次是快速排序,最后是归并排序。
若从稳定性来考虑,应选取归并排序,因为堆排序和快速排序都是不稳定的。
若从平均情况下的排序速度考虑,应该选择快速排序。

二维数组排序
1、使用array_multisort();
array_multisort(排序数组字段值的一维数组,待排序二维数组);
2、

<?php
function array_sort_by_any_row($array_name, $row_id, $order_type){
    $array_temp=array();
    foreach($array_name as $key=>$value){
        $array_temp[$key]=$value[$row_id];
    }
    if($order_type==="ASC"){ //顺序
        asort($array_temp);
    } else {
        arsort($array_temp);
    }
    $result_array=array();
    foreach($array_temp as $key=>$value){
        $result_array[$key]=$array_name[$key];
    }
    return $result_array;
}

$arr = array(array('num'=>5, 'value'=>6),
array('num'=>2, 'value'=>39),
array('num'=>36, 'value'=>29)
);

$sortarr = array_sort_by_any_row($arr, 'num', 'ASC');
print_r($sortarr);
?>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值