美文网首页
php常用的排序算法与二分法查找

php常用的排序算法与二分法查找

作者: ambition_wy | 来源:发表于2018-01-11 16:30 被阅读0次

    一 : 归并排序

    将两个的有序数列合并成一个有序数列,我们称之为"归并"。
    归并排序(Merge Sort)就是利用归并思想对数列进行排序。根据具体的实现,归并排序包括"从上往下"和"从下往上"2种方式。

    1. 从下往上的归并排序:将待排序的数列分成若干个长度为1的子数列,然后将这些数列两两合并;得到若干个长度为2的有序数列,再将这些数列两两合并;得到若干个长度为4的有序数列,再将它们两两合并;直接合并成一个数列为止。这样就得到了我们想要的排序结果

    2. 从上往下的归并排序:它与"从下往上"在排序上是反方向的。它基本包括3步:
      ① 分解 -- 将当前区间一分为二,即求分裂点 mid = (low + high)/2;
      ② 求解 -- 递归地对两个子区间a[low...mid] 和 a[mid+1...high]进行归并排序。递归的终结条件是子区间长度为1。
      ③ 合并 -- 将已排序的两个子区间a[low...mid]和 a[mid+1...high]归并为一个有序的区间a[low...high]。

    
      /**
          * 归并排序实现过程
          * @param Array $arr 待排序的区间数组
          * @param Int $start 第一个区间数组的起始位置
          * @param Int $mid 第一个区间数组的结束位置,第二个区间数组的起始位置
          * @param Int $end 第二个区间数组的结束位置
          * @return void */
        function merge(Array &$arr,$start,$mid,$end)
        {   
            $i = $start;
            $j = $mid + 1; 
            $k = 0;
            while($i <= $mid && $j <= $end)
            {
                if ($arr[$i] <= $arr[$j])    //判断两个区间数组各自数据的大小,并归类
                  $tmp[$k++] = $arr[$i++]; 
                else
                  $tmp[$k++] = $arr[$j++];
            } 
            while($i <= $mid)    //防止第一个区间有一个数据没有归类
            {
                $tmp[$k++] = $arr[$i++];
            }  
            while($j <= $end) //防止第二个区间有一个数据没有归类
            {
                $tmp[$k++] = $arr[$j++];  // 将排序后的元素,全部都整合到数组arr中。
            }   
            for ($i = 0; $i < $k; ++$i) 
               $arr[$start + $i] = $tmp[$i];
        } /**
          * 归并排序(从上往下)
          * @param Array $arr 待排序的数组
          * @param Int $start 数组起始位置
          * @param Int end 数组结束位置
          * @return void */
        function merge_sort(Array &$arr,$start=0,$end=0)
        { 
             $len = count($arr); 
             if($len <= 1 || $start >= $end) 
              return $arr;
             $mid = intval(($start + $end) / 2); //分区间
             merge_sort($arr,$start,$mid);
             merge_sort($arr,$mid+1,$end);
    
             merge($arr,$start,$mid,$end);
        }
    
       //从下往上与此刚好相反
    
    

    二 : 快速排序

    通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。快速排序主体算法时间运算量约 O(log2n) ,划分子区函数运算量约 O(n) ,所以总的时间复杂度为 O(nlog2n) ,它显然优于冒泡排序 O(n2). 可是算法的优势并不是绝对的。试分析,当原文件关键字有序时,快速排序时间复杂度是 O(n2), 这种情况下快速排序不快。而这种情况的冒泡排序是 O(n), 反而很快。在原文件记录关键字无序时的多种排序方法中,快速排序被认为是最好的一种排序方法。

    
     /**
          * 快速排序
          * @param Array $arr 待排序的数组
          * @return Array 排序后的数组 */
        function quick_sort(Array $arr)
        { 
            $len = count($arr); 
            if($len <= 1) 
               return $arr; 
            $tmp = $arr[0];
            $left_arr = [];
            $right_arr = []; 
            for($i = 1; $i < $len; ++$i)
            { 
                if($arr[$i] <= $tmp) 
                   $left_arr[] = $arr[$i];
               else
                   $right_arr[] = $arr[$i];
            } //递归分类
            $left_arr = quick_sort($left_arr); 
            $right_arr = quick_sort($right_arr);
            return array_merge($left_arr,array($tmp),$right_arr);
        } 
    
    

    三 :冒泡排序

    两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。该算法的时间复杂度为O(n2)。但是,当原始关键字序列已有序时,只进行一趟比较就结束,此时时间复杂度为O(n)。

    
     /**
          * 冒泡排序
          * @param Array $arr 待排序的数组
          * @return Array 排序后的数组 */
        function bubble_sort(Array $arr)
        { 
            $len = count($arr);
            for($i = 0; $i < $len; ++$i)
            {
                 for($j = $len - 1; $j > $i; --$j)
                { 
                     if($arr[$j] < $arr[$j-1])
                    { 
                        $tmp = $arr[$j]; 
                        $arr[$j] = $arr[$j-1];
                        $arr[$j-1] = $tmp;
                    }
                }
            } 
            return $arr;
        }
    
    

    四 :插入排序

    每次将一个待排序的数据元素插入到前面已经排好序的数列中,使数列依然有序,知道待排序数据元素全部插入完为止。如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择

    
    /**
          * 插入排序
          * @param Array $arr 待排序的数组
          * @return Array 排序后的数组 */
        function insert_sort(Array $arr)
        { 
            $len = count($arr);
            for($i = 1; $i < $len; ++$i)
            {
                $tmp = $arr[$i]; $j = $i - 1; //把数据插入到合适的位置(交换位置)
                while($j >= 0 && $arr[$j] > $tmp)
                {
                   $arr[$j+1] = $arr[$j]; 
                   $arr[$j] = $tmp;
                   --$j;
                }
            } 
            return $arr;
        }
    
    

    五 :选择排序

    每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。时间复杂度为o(n2),不稳定排序,适合规模比较小的

    
     /**
          * 选择排序
          * @param Array $arr 待排序的数组
          * @return Array 排序后的数组 */
        function select_sort(Array $arr)
        {
            $len = count($arr); 
            for($i = 0; $i < $len; ++$i)
            {
                $k = $i;    //标记当前索引
                for($j = $i + 1; $j < $len; ++$j)
                {
                    if($arr[$j] < $arr[$k])
                      $k = $j; //获取当前最小值索引
                    if($k != $i) //如果最小值得索引发生变化
                    { 
                         $tmp = $arr[$i];
                         $arr[$i] = $arr[$k]; 
                         $arr[$k] = $tmp;
                    }
                }
            } 
              return $arr;
        }
    

    六 :二分查找

    
     /**
          * 二分查找
          * @param Array $arr 待查找的数组
          * @param Int $key 要查找的关键字
          * @return Int */
        function bin_search(Array $arr,$key)
        {
            $high = count($arr); 
            if($high <= 0) 
               return 0;
            $low = 0;
            while($low <= $high)
            {   
                //当前查找区间arr[low..high]非空
                $mid=intval(($low + $high) / 2); 
                if($arr[$mid] == $key) 
                  return $mid; //查找成功返回
                if($arr[$mid] > $key) 
                   $high = $mid - 1; //继续在arr[low..mid-1]中查找
                else
                   $low = $mid + 1; //继续在arr[mid+1..high]中查找
           }
            return 0; //当low>high时表示查找区间为空,查找失败
         } 
        $arr = array(1,2,4,6,10,40,50,80,100,110); 
        echo bin_search($arr,80);
    

    文章转至

    相关文章

      网友评论

          本文标题:php常用的排序算法与二分法查找

          本文链接:https://www.haomeiwen.com/subject/htktoxtx.html