php常用排序算法

一 冒泡排序

// 冒泡排序
function bubble_sort($arr)
{
    $len = count($arr);
    for ($i = 0; $i < $len -1; $i++) {//循环对比的轮数
        for ($j = 0; $j < $len - $i - 1; $j++) {//当前轮相邻元素循环对比
            if ($arr[$j] > $arr[$j + 1]) {//如果前边的大于后边的
                $tmp = $arr[$j];//交换数据
                $arr[$j] = $arr[$j + 1];
                $arr[$j + 1] = $tmp;
            }
        }
    }
    return $arr;
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
冒泡排序O(n)O(n2)O(n2)稳定O(1)

二 直接插入排序

function InsertSort(array &$arr){
    $count = count($arr);
    //数组中第一个元素作为一个已经存在的有序表
    for($i = 1;$i < $count;$i ++){
        $temp = $arr[$i];      //设置哨兵
        for($j = $i - 1;$j >= 0 && $arr[$j] > $temp;$j --){
            $arr[$j + 1] = $arr[$j];       //记录后移
        }
        $arr[$j + 1] = $temp;      //插入到正确的位置
    }
    return $arr;
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
插入排序O(n)O(n2)O(n2)稳定O(1)

三 希尔排序

<?php

//希尔排序(对直接插入排序的改进)

function ShellSort(array $arr)
{
    $len   = count($arr);
    $count = 0;
    $f     = 5; // 定义因子
    $h     = 1; // 最小为1
    while ($h < $len / $f)
    {
        $h = $f * $h + 1; // 1, 4, 13, 40, 121, 364, 1093, ...
    }
    while ($h >= 1)
    {
        // 将数组变为h有序
        for ($i = $h; $i < $len; $i++)
        { 
            // 将a[i]插入到a[i-h], a[i-2*h], a[i-3*h]... 之中 (算法的关键
            for ($j = $i; $j >= $h&&$arr[$j] < $arr[$j - $h]; $j -= $h)
            {
                $tmp         = $arr[$j];
                $arr[$j]     = $arr[$j - $h];
                $arr[$j - $h]= $tmp;
            }
         }
         $h = intval($h / $f);
    }
    return $arr;
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
希尔排序O(nlog2n)O(n2)O(n2)不稳定O(1)

四 选择排序

/**
*    选择排序
*    在一列数字中,选出最小数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
*/
function SelectSort($arr)
{
    $len   = count($arr);
    for ($i = 0; $i < $len - 1; $i++)
    {
        //定义最小位置
        $minIndex = $i;
        for ($j = $i + 1; $j < $len; $j++)
        {
            if ($arr[$j] < $arr[$minIndex])
            {
                $minIndex = $j;
            }
        }
        if ($i != $minIndex)
        {
            $tmp            = $arr[$i];
            $arr[$i]        = $arr[$minIndex];
            $arr[$minIndex] = $tmp;
        }
    }
    return $arr;
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
选择排序O(n2)O(n2)O(n2)不稳定O(1)

五 快速排序

<?php

function quick_sort($a)
{
    // 判断是否需要运行,因下面已拿出一个中间值,这里<=1
    if (count($a) <= 1) {
        return $a;
    }
    $middle = $a[0]; // 中间值
    $left = array(); // 接收小于中间值
    $right = array();// 接收大于中间值
    // 循环比较
    for ($i=1; $i < count($a); $i++) { 
        if ($middle < $a[$i]) {
            // 大于中间值
            $right[] = $a[$i];
        } else {
            // 小于中间值
            $left[] = $a[$i];
        }
    }
    // 递归排序划分好的2边
    $left = quick_sort($left);
    $right = quick_sort($right);

    // 合并排序后的数据,别忘了合并中间值
    return array_merge($left, array($middle), $right);
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
快速排序O(nlog2n)O(n2)O(nlog2n)不稳定O(log2n)~O(n)

六 堆排序

function HeapSort($arr)
{
    $len   = count($arr);
    //先将数组构造成大根堆(由于是完全二叉树,所以这里用floor($count/2)-1,下标小于或等于这数的节点都是有孩子的节点)
    for ($i = floor($len / 2) - 1; $i >= 0; $i--) //14=29 13=27 12=25 11=23
    {
        $temp  = $arr[$i];
        $start = $i;
        //沿关键字较大的孩子节点向下筛选
        //左右孩子计算(我这里数组开始下标识 0)
        //左孩子2 * $start + 1,右孩子2 * $start + 2
        for ($j = 2 * $start + 1; $j < $len - 1; $j = 2 * $j + 1)
        {
            if ($j != $len && $arr[$j] < $arr[$j + 1])
            {
                $j++; //转化为右孩子
            }
            if ($temp >= $arr[$j])
            {
                break; //已经满足大根堆
            }
            //将根节点设置为子节点的较大值
            $arr[$start] = $arr[$j];
            //继续往下
            $start = $j;
        }
        $arr[$start] = $temp;
    }

    for ($i = $len - 1; $i >= 0; $i--)
    {
        //将堆顶元素与最后一个元素交换,获取到最大元素(交换后的最后一个元素),将最大元素放到数组末尾
        $tmp     = $arr[0];
        $arr[0]  = $arr[$i];
        $arr[$i] = $tmp;

        //经过交换,将最后一个元素(最大元素)脱离大根堆,并将未经排序的新树($arr[0...$i-1])重新调整为大根堆
        $temp  = $arr[0];
        $start = 0;
        for ($j = 2 * $start + 1; $j <= $i - 1; $j = 2 * $j + 1)
        {
            if ($j != $i - 1 && $arr[$j] < $arr[$j + 1])
            {
                $j++;
            }
            if ($temp >= $arr[$j])
            {
                break;
            }
            $arr[$start] = $arr[$j];
            $start       = $j;
        }
        $arr[$start] = $temp;
    }
    return $arr;
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
堆排序O(nlog2n)O(nlog2n)O(nlog2n)不稳定O(1)

七 归并排序

// 归并排序主程序
function mergeSort($arr) {
    $len = count($arr);
    if ($len <= 1) {
        return $arr;
    } // 递归结束条件, 到达这步的时候, 数组就只剩下一个元素了, 也就是分离了数组

    $mid = intval($len / 2); // 取数组中间
    $left = array_slice($arr, 0, $mid); // 拆分数组0-mid这部分给左边left
    $right = array_slice($arr, $mid); // 拆分数组mid-末尾这部分给右边right
    $left = mergeSort($left); // 左边拆分完后开始递归合并往上走
    $right = mergeSort($right); // 右边拆分完毕开始递归往上走
    $arr = merge($left, $right); // 合并两个数组,继续递归

    return $arr;
}

// merge函数将指定的两个有序数组(arrA, arr)合并并且排序
function 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);
}
排序算法最好时间分析最差时间分析平均时间复杂度稳定度空间复杂度
归并排序O(nlog2n)O(nlog2n)O(nlog2n)稳定O(n)

时间复杂度有:常数阶O(1)>对数阶O(log2n)>线性阶O(n)>线性对数阶O(nlog2n)>平方阶O(n2)>立方阶O(n3)

衍生时间复杂度

sum = n*(n+1)/2;        //时间复杂度O(1)
 

for(int i = 0; i < n; i++){
    printf("%d ",i);
}                       
//时间复杂度O(n)
 

for(int i = 0; i < n; i++){
    for(int j = 0; j < n; j++){
        printf("%d ",i);
    }
}               
//时间复杂度O(n^2)
 

for(int i = 0; i < n; i++){
    for(int j = i; j < n; j++){
        printf("%d ",i);
    }
}   
//运行次数为(1+n)*n/2
//时间复杂度O(n^2)

int i = 0, n = 100;
while(i < n){
    i = i * 2;
}
//设执行次数为x. 2^x = n 即x = log2n
//时间复杂度O(log2n)

                                                                                                                                   by 沐澍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值