php 排序算法

  • 冒泡排序

冒泡排序大概的意思是依次比较相邻的两个数,然后根据大小做出排序,直至最后两位数。由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。但其实在实际过程中也可以根据自己需要反过来用,大数往前放,小数往后放。

<?php

/**
 * 冒泡排序
 * @param $arr
 * @return mixed
 */
function bubbleSort($arr)
{
    $len = count($arr);
    if ($len <= 1) {
        return $arr;
    }

    // 第一层可以理解为从数组中键为0开始循环到最后一个
    for ($i = 0; $i < $len ; $i++) {
        // 第二层为从$i+1的地方循环到数组最后
        for ($j = $i+1; $j < $len; $j++) {
            // 比较数组中两个相邻值的大小
            if ($arr[$i] > $arr[$j]) {
                $temp = $arr[$i]; // 这里临时变量,存贮$i的值
                $arr[$i] = $arr[$j]; // 第一次更换位置
                $arr[$j] = $temp; // 完成位置互换
            }
        }
    }

    return $arr;
}

$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];

$arr = bubbleSort($arr);

print_r($arr);

输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )

 

  • 插入排序

它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。就像抓扑克牌,抓一张,然后再手里已经部分已经排好序的手牌的找到位置插进去。

$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];

//插入排序是一种逻辑上非常好理解的排序方式,整个排序的核心就是不断在当前已经排好部分数据的数组里,
//找到合适的位置插入新数据。就像抓扑克牌,抓一张,然后再手里已经部分已经排好序的手牌的找到位置插进去。

/**
 * 插入排序
 * @param $arr
 * @return mixed
 */
function insertSort($arr)
{
    //获取数组单元个数
    $len = count($arr);

    if ($len <= 1) {
        return $arr;
    }

    //外层循环用于从未排序区域中取出待排序元素
    for ($i = 1; $i < $len; $i++) {
        //获取当前需要插入已排序区域的元素值
        $temp = $arr[$i];
        //内层循环用于从已排序区域寻找待排序元素的插入位置
        for ($j = $i - 1; $j >= 0; $j--) {
            //如果$arr[$i]比已排序区域的$arr[$j]小,就后移$arr[$j]
            if ($temp < $arr[$j]) {
                $arr[$j + 1] = $arr[$j];
                $arr[$j] = $temp;
            } else {
                //如果$arr[$i]不小于$arr[$j],则对已排序区无需再排序
                break;
            }
        }
    }
    return $arr;
}

$arr = insertSort($arr);

print_r($arr);

输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )

  • 选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];

/**
 * 选择排序
 * @param $arr
 * @return mixed
 */
function selectSort($arr)
{
    //获取数组单元个数
    $len = count($arr);

    if ($len <= 1) {
        return $arr;
    }

    for ($i = 0; $i < $len - 1; $i++) {
        // 当前值的位置
        $key = $i;
        for ($j = $i + 1; $j < $len; $j++) {
            // 相邻值进行比较,条件成立替换当前值
            if ($arr[$key] > $arr[$j]) {
                $key = $j;
            }
        }

        if ($key != $i) {
            // 交换位置
            $temp = $arr[$key];
            $arr[$key] = $arr[$i];
            $arr[$i] = $temp;
        }
    }

    return $arr;
}

$arr = selectSort($arr);

print_r($arr);

输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )

 

  • 归并排序

假设当前需要从小到大进行排序,归并排序的核心思路是,把大的数组,不停地拆成小的数组,直到拆得最小,然后再把小数组两两排序合并,再将结果不停地进行一次次排序的合并。

算法描述

  • 把长度为n的输入序列分成两个长度为n/2的子序列;
  • 对这两个子序列分别采用归并排序;
  • 将两个排序好的子序列合并成一个最终的排序序列。

$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];


/**
 * mergeSort 归并排序
 * 是开始递归函数的一个驱动函数
 * @param &$arr array 待排序的数组
 */
function mergeSort(&$arr)
{
    $len = count($arr);//求得数组长度

    mSort($arr, 0, $len - 1);
}

/**
 * 实际实现归并排序的程序
 * @param &$arr array 需要排序的数组
 * @param $left int 子序列的左下标值
 * @param $right int 子序列的右下标值
 */
function mSort(&$arr, $left, $right)
{

    if ($left < $right) {
        //说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
        //计算拆分的位置,长度/2 去整
        $center = floor(($left + $right) / 2);
        //递归调用对左边进行再次排序:
        mSort($arr, $left, $center);
        //递归调用对右边进行再次排序
        mSort($arr, $center + 1, $right);
        //合并排序结果
        mergeArray($arr, $left, $center, $right);
    }
}

/**
 * 将两个有序数组合并成一个有序数组
 * @param &$arr , 待排序的所有元素
 * @param $left , 排序子数组A的开始下标
 * @param $center , 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
 * @param $right , 排序子数组B的结束下标(开始为$center+1)
 */
function mergeArray(&$arr, $left, $center, $right)
{
    //设置两个起始位置标记
    $a_i = $left;
    $b_i = $center + 1;
    while ($a_i <= $center && $b_i <= $right) {
        //当数组A和数组B都没有越界时
        if ($arr[$a_i] < $arr[$b_i]) {
            $temp[] = $arr[$a_i++];
        } else {
            $temp[] = $arr[$b_i++];
        }
    }
    //判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
    while ($a_i <= $center) {
        $temp[] = $arr[$a_i++];
    }
    //判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
    while ($b_i <= $right) {
        $temp[] = $arr[$b_i++];
    }

    //将$arrC内排序好的部分,写入到$arr内:
    for ($i = 0, $len = count($temp); $i < $len; $i++) {
        $arr[$left + $i] = $temp[$i];
    }

}

mergeSort($arr);
  • 快速排序

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

$arr = [8, 1, 2, 5, 4, 3, 7, 6, 9];

function quickSort($arr)
{
    $count = count($arr);

    if ($count < 2) {
        return $arr;
    }

    $leftArray = $rightArray = array();
    $middle = $arr[0];// 基准值

    for ($i = 1; $i < $count; $i++) {
        // 小于基准值,存入左边;大于基准值,存入右边
        if ($arr[$i] < $middle) {
            $leftArray[] = $arr[$i];
        } else {
            $rightArray[] = $arr[$i];
        }
    }

    $leftArray = quickSort($leftArray);
    $rightArray = quickSort($rightArray);

    return array_merge($leftArray, array($middle), $rightArray);
    // 倒序
    // return array_merge($rightArray, array($middle), $leftArray);
}

$arr = quickSort($arr);


print_r($arr);

 

 

注:快速排序在常规排序里综合排名最高的排序算法。 快速排序在工程实践中应用较多,比如 PHP 数组的 sort 函数底层就是基于快速排序来实现的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值