PHP常见算法

排序

冒泡排序

依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面。

php 复制代码
$arr = [8,1,10,9,5,7];
function bubbleSort($arr){
    // 外层 for 循环控制循环次数
    for ($i=0; $i<count($arr) ; $i++) {
        //内层 for 循环进行两数交换,找每次的最大数,排到最后
        for ($j=0; $j < count($arr)-1; $j++) {

            //数组里第一个和第二个对比,如果1>2,执行数值互换
            if($arr[$j] >$arr[$j+1]){
               
                $x = $arr[$j];  //第一赋给一个变量
                $arr[$j] = $arr[$j+1]; //第二赋给第一
                $arr[$j+1] = $x;  //把变量给第二,结果就是1,2的数值互换
                // $a=10;
                // $b=20;
                // $x=$a; $x=10
                // $a=$b; $a=20
                // $b=$X; $b=10
            }
        }
    }
    return $arr;
}
print_r(bubbleSort($arr));

快速排序

快速排序是对冒泡排序的一种改进。

设置一个基准元素,通过排序将需要排序的数据分割成两个部分,其中一部分的所有数据比基准元素小,另一部分的所有数据比基准元素大,然后对这两部分数据分别进行递归快速排序,最后将得到的数据和基准元素进行合并,就得到了所需数据。

php 复制代码
$arr = [8,1,10,9,5,7];
function quickSort($arr){
    $lenth = count($arr);//获取数组个数
    if($lenth <= 1){//小于等于一个不用往下走了
        return $arr;
    }
    //选择基准元素。一般选第一个或最后一个
    $first = $arr[0];
    $left = array();//接收小于基准元素的值
    $right = array();//接收大于基准元素的值
    //循环从1开始,因为基准元素是0
    for($i=1;$i<$lenth;$i++){
        if($arr[$i]<$first){//小于基准元素的值
            $left[] = $arr[$i];
        }else{//大于基准元素的值
            $right[] = $arr[$i];
        }
    }
    //递归排序
    $left = quickSort($left);
    $right = quickSort($right);
    //合并返回数组
    return array_merge($left,array($first),$right);
}
print_r(quickSort($arr));

选择排序

1.找到数组中最小的元素,拎出来,将它和数组的第一个元素交换位置;

2.在剩下的元素中继续寻找最小的元素,拎出来,和数组的第二个元素交换位置;

3.如此循环,直到整个数组排序完成。

php 复制代码
$arr = [8,1,10,9,5,7];
function selectSort($arr){
    //实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数,$i 当前最小值的位置, 需要参与比较的元素
    for($i=0, $len=count($arr); $i<$len-1; $i++){
        //先假设最小的值的位置
        $p = $i;
        //$j 当前都需要和哪些元素比较,$i 后边的。
        for($j=$i+1; $j<$len; $j++) {
            //$arr[$p] 是 当前已知的最小值
            if($arr[$p] > $arr[$j]){
                //比较,发现更小的,记录下最小值的位置;并且在下次比较时,应该采用已知的最小值进行比较。
                $p = $j;
            }
        }
        //已经确定了当前的最小值的位置,保存到$p中。如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可。
        if($p != $i){
            $tmp = $arr[$p];
            $arr[$p] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }
 
    return $arr;
}

print_r(selectSort($arr));

插入排序

每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。

php 复制代码
$arr = [8,1,10,9,5,7];
function insertSort($arr){
    $count = count($arr);   
    for($i=1; $i<$count; $i++){         
        $tmp = $arr[$i];        
        $j = $i - 1;        
        while(isset($arr[$j]) && $arr[$j] > $tmp){             
            $arr[$j+1] = $arr[$j];          
            $arr[$j] = $tmp;            
            $j--;           
        }    
    }    
    return $arr; 
} 

print_r(insertSort($arr));

希尔排序

希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。

希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

php 复制代码
$arr = [8,1,10,9,5,7];
function shellSort(&$arr){
    if(!is_array($arr))return;$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){
                $temp=$arr[$j];
                $arr[$j]=$arr[$j+$gap];
                $arr[$j+$gap]=$temp;
            }
        }
    }
    return $arr;
}

print_r(shellSort($arr));

查找

二分查找

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

php 复制代码
/**
 * 二分查找(Binary Search)算法,也叫折半查找算法。二分查找的思想非常简单,有点类似分治的思想。
 * 二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比,
 * 将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。
 *
 * 循环写法
 * @param array $array      待查找的数组
 * @param int $findVal      要查找的值
 * @return int              返回找到的数组键
 */
function binarySearch($array, $findVal)
{
    // 非数组或者数组为空,直接返回-1
    if (!is_array($array) || empty($array)) {
        return -1;
    }
    // 查找区间,起点和终点
    $start = 0;
    $end = count($array) - 1;
    while ($start <= $end) {
        // 以中间点作为参照点比较,取整数
        $middle = intval(($start + $end) / 2);
 
        if ($array[$middle] > $findVal) {
            // 查找数比参照点小,则要查找的数在左半边
            // 因为 $middle 已经比较过了,这里需要减1
            $end = $middle - 1;
 
        } elseif ($array[$middle] < $findVal) {
            // 查找数比参照点大,则要查找的数在右半边
            // 因为 $middle 已经比较过了,这里需要加1
            $start = $middle + 1;
 
        } else {
            // 查找数与参照点相等,则找到返回
            return $middle;
        }
    }
    // 未找到,返回-1
    return -1;
}
 
// 调用
$array = [10,12,16,19,20,34,56,78,84,95,100];
echo binarySearch($array, 84);

/**
 * 递归写法
 * @param array $array  待查找的数组
 * @param int $findVal  要查找的值
 * @param int $start    查找区间,起点
 * @param int $end      查找区间,终点
 * @return int          返回找到的数组键
 */
function binSearch($array, $findVal, $start, $end)
{
    // 以中间点作为参照点比较,取整数
    $middle = intval(($start + $end) / 2);
    if ($start > $end) {
        return -1;
    }
    if ($findVal > $array[$middle]) {
        // 查找数比参照点大,则要查找的数在右半边
        return binSearch($array, $findVal, $middle + 1, $end);
 
    } elseif ($findVal < $array[$middle]) {
        // 查找数比参照点小,则要查找的数在左半边
        return binSearch($array, $findVal, $start, $middle - 1);
 
    } else {
        return $middle;
    }
}
 
// 调用
$arr = [10,12,16,19,20,34,56,78,84,95,100];
var_dump(binSearch($arr, 95, 0, count($arr)-1));

ps:未完待续

相关推荐
江畔柳前堤7 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore8 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考9 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX10 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面10 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号11 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽11 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI11 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者13 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者13 小时前
【征程6】校准量化中HistogramObserver解析
算法