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

一 : 归并排序

将两个的有序数列合并成一个有序数列,我们称之为"归并"。
归并排序(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);
时间: 2024-08-10 21:31:08

php常用的排序算法与二分法查找的相关文章

几种常用的排序算法总结

主要针对于插入排序,交换(冒泡和快速),选择,堆排序,归并这几种排序的基本原理和时间复杂度,及空间复杂度的一个总结. 一.插入排序 基本执行过程:3  5  2  7  9  8 1.从小到大:从第二个数开始,每次比较都与前边的几个数进行比较 但是从大到小,要先与前边排好序的几个数中的最大的开始进行比较即倒序比较,依次往前推. 如:5 先与3进行比较,比3大,所以直接排在3的后边为:3 5: 2要先与5进行比较,比5小,再与3比较,比3小,所以排序后为 2 3 5: 7要先与5比,比5大,所以直

顺序表的冒泡排序算法及二分法查找代码实现

本文主要实现了比较经典的冒泡排序算法(对已经有序或者基本有序的顺序表复杂度大大降低),和二分法查找,各位看官看代码吧 //冒泡排序算法及二分法查找 #include "stdio.h" typedef struct { int key; }SSTable_Elem_Type; typedef struct { SSTable_Elem_Type*elem; int length; }SSTable_Typedef; void Bubble_Sort(SSTable_Typedef*ST

JavaScript实现常用的排序算法

▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排序.希尔排序.直接选择排序 ▓▓▓▓▓▓ 交换排序 交换排序是一类在排序过程中借助于交换操作来完成排序的方法,基本思想是两两比较排序记录的关键字,如果发现两个关键字逆序,则将两个记录位置互换,重复此过程,直到该排序列中所有关键字都有序为止,接下来介绍交换排序中常见的冒泡排序和快速排序 ▓▓▓▓▓▓

【计算机基础】 常用的排序算法的时间复杂度和空间复杂度

常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n) 选择排序 O(n2) O(n2) 稳定 O(1) 二叉树排序 O(n2) O(n*log2n) 不一顶 O(n) 插入排序 O(n2) O(n2) 稳定 O(1) 堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1) 希尔排序 O O 不稳定 O(1) 1

7 种常用的排序算法-视觉直观感受

7 种常用的排序算法-可视化 1. 快速排序 介绍: 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性. 步骤: 从数列中挑出一个元素,称为 “基准”(pivot),

java SE 常用的排序算法

java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) D.归并排序 E.分配排序(基数排序) 以下算法都是可以实现的,但是什么情况使用什么算法都是根据实际情况选用的. 如果有用的话就顶起吧,谢谢. import java.util.ArrayList; import java.util.List; public class Sort { // test

C#中常用的排序算法的时间复杂度和空间复杂度

常用的排序算法的时间复杂度和空间复杂度 常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 O(n2) O(n*log2n) 不稳定 O(log2n)~O(n) 选择排序 O(n2) O(n2) 稳定 O(1) 二叉树排序 O(n2) O(n*log2n) 不一顶 O(n) 插入排序 O(n2) O(n2) 稳定 O(1) 堆排序 O(n*log2n) O(n*log2n) 不稳定 O(1)

八种常用的排序算法(转)

下面要讲到的8种排序都属于内部排序,既在内存中完成,主要从理论原理方面来分析的.    插入排序 ①直接插入排序 例:六个数12 15 9 20  6 31 24 用直接插入排序,如下图: 思路: 第一步:从给出的六个数中,随便拿出一个数,比如12,形成一个有序的数据序列(一个数当然是有序的数据序列了,不看12之外的数,就当其他的数不存在): 第二步:从剩下的五个数中挑出一个数来,比如15,和刚才的12作比较,12<15,因此,放在12后面,形成数据序列12 15: 第三步:从剩下的四个数中挑出

常用的排序算法和时间复杂度

1. 数据结构部分 数据结构中常用的操作的效率表 通用数据结构 查找 插入 删除 遍历 数组 O(N) O(1) O(N) - 有序数组 O(logN) O(N) O(N) O(N) 链表 O(N) O(1) O(N) - 有序链表 O(N) O(N) O(N) O(N) 二叉树 O(logN) O(logN) O(logN) O(N) 二叉树(最坏) O(N) O(N) O(N) O(N) 红黑树 O(logN) O(logN) O(logN) O(N) 2-3-4树 O(logN) O(lo