• PHP版常用算法


    冒泡

    //冒泡
    //逐行对比,满足条件则交换
    function bubbleSort($arrData,$sort = 'desc')
    {
        if(empty($arrData)) return $arrData;
    
        //默认有序
        $isSorted = true;
        $nCount = count($arrData);
        for($i = 0; $i < $nCount; $i++) {
    
            //对比次数随着循环逐渐减少,因为后面的数据已经处理为有序
            for($j = 0; $j < ($nCount - $i - 1); $j++) {
                //执行判断
                $isChange = $sort == 'desc' ? $arrData[$j] < $arrData[$j+1] : $arrData[$j] > $arrData[$j+1];
    
                if($isChange) {
                    //首次对比,判断是否有序
                    $isSorted = false;
    
                    $temp = $arrData[$j];
                    $arrData[$j] = $arrData[$j+1];
                    $arrData[$j+1] = $temp;
                }
            }
    
            if($isSorted) break;
        }
    
        return $arrData;
    }

    快速排序

    //快速排序
    //选取一个标准,和其他数据对比后将数据分为两批,递归执行后合并
    function quickSort(&$arr, $sort = 'asc'){
    
        //检查数据,多于一个数据才执行
        $nCount = count($arr);
        if($nCount > 1) {
            //选取标准(第一个数据)
            $nStandard = $arr[0];
            $arrLeftData = [];
            $arrRightData = [];
            //遍历,注意这里从1开始比较
            for($i = 1; $i < $nCount; $i++) {
    
                if($sort == 'desc') {
                    $arr[$i] > $nStandard ? $arrLeftData[] = $arr[$i] : $arrRightData[] = $arr[$i];
                } else {
                    $arr[$i] > $nStandard ? $arrRightData[] = $arr[$i] : $arrLeftData[] = $arr[$i];
                }
            }
            $arr = array_merge($this->quickSort($arrLeftData, $sort), array($nStandard), $this->quickSort($arrRightData, $sort));
        }
        return $arr;
    }
    

    归并排序

    //利用归并(合并)的思想实现的排序方法。
    //它的原理是假设初始序列含有 n 个元素,则可以看成是 n 个有序的子序列,每个子序列的长度为 1,然后两两归并
    //得到n/2个长度为2或1 的有序序列;再两两归并,······,如此重复
    //直至得到一个长度为 n 的有序序列为止,这种排序方法就成为 2 路归并排序
    
    //merge函数将指定的两个有序数组(arr1,arr2)合并并且排序
    //我们可以找到第三个数组,然后依次从两个数组的开始取数据哪个数据小就先取哪个的,然后删除掉刚刚取过的数据
    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 = $this->al_merge_sort($left_arr);//左边拆分完后开始递归合并往上走
        $right_arr = $this->al_merge_sort($right_arr);//右边拆分完毕开始递归往上走
    
        $arr = $this->al_merge($left_arr, $right_arr);//合并两个数组,继续递归
        return $arr;
    }

    二分查找

    //二分查找
    //假设数据是按升序排序的,对于给定值x,从序列的中间位置开始比较,如果当前位置值等于x,则查找成功;
    //若x小于当前位置值,则在数列的前半段中查找;若x大于当前位置值则在数列的后半段中继续查找,直到找到为止
    function binSearch($toSearch,$arr)
    {
        //确定当前的检索范围
        $nCount = count($arr);
        //低位键,初始为0
        $nLowNum = 0;
        //高位键,初始为末尾 
        $nHighNum = $nCount - 1;
    
        while($nLowNum <= $nHighNum) {
            //选定大概中间键
            $nMiddleNum = intval(($nHighNum + $nLowNum)/2);
    
            if($arr[$nMiddleNum] > $toSearch) {
                //比检索值大
                $nHighNum = $nMiddleNum - 1;
            } elseif ($arr[$nMiddleNum] < $toSearch) {
                //比检索值小
                $nLowNum = $nMiddleNum + 1;
            } else {
                return $nMiddleNum;
            }
        }
    
        return false;
    }

    顺序查找

    //顺序查找
    function seqSearch($arr,$toSearch)
    {
        $nCount = count($arr);
    
        for ($i=0; $i < $nCount; $i++) {
            if ($arr[$i] == $toSearch) {
                return $i;
            }
        }
        return -1;
    }

    选择排序

    //在第一次循环中,假设第一个数是最小的;然后跟第二个数比较,一直比到最后,找出最小值,然后把最小值跟第一个数的位置互换;
    //再进行下一次循环,找出最小值跟第二个位置的数互换;一直循环数组的个数减去1次;数组就成了有序的了 
    function selectSort($arr)
    {
    
        $nCount = count($arr);
        //遍历取得需要排序的数
        for($i = 0; $i < $nCount; $i++) {
    
            //选择需要比较的数,从$i开始到结束
            for($j = $i + 1; $j < $nCount; $j++) {
                //比较
                if($arr[$j] < $arr[$i]) {
                    $temp = $arr[$i];
                    $arr[$i] = $arr[$j];
                    $arr[$j] = $temp;
                }
            }
        }
        return $arr;  
    }

    外部排序+多路归并

    思路参考: 
    https://blog.csdn.net/itermeng/article/details/77824866
    
    面试中经常问到一些关于 并行计算 或者 在一台内存不多的机器上进行大文件排序 的问题,这些其实思路都可以借助外部排序+多路归并去解决:
    
    只能一部分放在放在内存数组中,另一部分放在内存之外(硬盘或网络其它节点),这就是所谓的外部排序;
    归并排序:将数据分为左右两部分,分别排序,再把两个有序子数组进行归并;
    重点就是归并过程,就是两个已排序好的数组来比较头部的元素,取最小值放入最终数组中;
    1
    2
    3
    思路:
    
    第一步:将数据进行切分,例如以100m将1G的文件分为10组,将每一段数据分配到外部,切分的大小符合节点内存大小限制;
    第二步:这样每个节点各自对分配数据进行排序,采用归并排序或快速排序皆可(多节点则节点处理,单机则逐个处理);
    第三步:将每个排序好的节点按照归并算法整合到一个节点(多路归并);
  • 相关阅读:
    28完全背包+扩展欧几里得(包子凑数)
    HDU 3527 SPY
    POJ 3615 Cow Hurdles
    POJ 3620 Avoid The Lakes
    POJ 3036 Honeycomb Walk
    HDU 2352 Verdis Quo
    HDU 2368 Alfredo's Pizza Restaurant
    HDU 2700 Parity
    HDU 3763 CDs
    POJ 3279 Fliptile
  • 原文地址:https://www.cnblogs.com/qczy/p/11257213.html
Copyright © 2020-2023  润新知