• 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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    快速排序

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

    $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
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    选择排序

    1.找到数组中最小的元素,拎出来,将它和数组的第一个元素交换位置;
    2.在剩下的元素中继续寻找最小的元素,拎出来,和数组的第二个元素交换位置;
    3.如此循环,直到整个数组排序完成。

    $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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    插入排序

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

    $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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    希尔排序

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

    $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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    查找

    二分查找

    二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
    首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

    /**
     * 二分查找(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));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    ps:未完待续

  • 相关阅读:
    Oracle12c新特性大全 存储资源隔离+flex+diskgroup
    安杰思提交注册:预计2022年度收入不低于3.5亿元,同比增长15%
    Python中的日期和时间
    3.10 haas506 2.0开发教程-example-TFT
    表白墙网站练习【前端+后端+数据库】
    STM32——SPI通信
    云原生爱好者周刊:使用 eBPF 实现 PostgreSQL 的可观测性
    Kubernetes API的流编解码器StreamSerializer
    水利设计公司资质怎么办理,办理水利设计有限公司及水利丙级资质申请程序
    字符串的创建(直接赋值与new的区别)- 字符串常量池
  • 原文地址:https://blog.csdn.net/heshihu2019/article/details/132699273