• 常用排序算法记录


    一、前言

        简单记录一下常用的算法排序,以便复习

    二、快速排序

      主要思想:

      (1)在数据集之中,选择一个元素作为"基准"(pivot)。

      (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。

      (3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

           代码实现:

    function quickSort($arr){
        $length = count($arr);
        $arr_left = array();
        $arr_right = array();
        if($length <= 1){
            return $arr;
        }
        $pivot = $arr[0];
        for($i = 1 ;$i < $length; $i ++){
            if($arr[$i] <= $pivot){
                $arr_left[] = $arr[$i];
            }else{
                $arr_right[] = $arr[$i];
            }
        }
        $arr_left = quick_sort($arr_left);
        $arr_right = quick_sort($arr_right);
        $arr = array_merge($arr_left,array($pivot),$arr_right);
        return $arr;
    }
    
    $arr = array(2,1,4,5,3);
    var_dump(quickSort($arr));

    三、归并排序

      主要思想:

    主要是利用 分治法 ;

    首先考虑下如何将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。

    归并排序,就是 将数组分成二组A,B,然后分别将A,B再分成两组,依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先递归的分解数列,再合并数列就完成了归并排序。

        步骤:

    1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

    2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

    3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

    4. 重复步骤3直到某一指针达到序列尾

    5. 将另一序列剩下的所有元素直接复制到合并序列尾

      代码实现: 

    /**
    * mergeSort 归并排序
    * 是开始递归函数的一个驱动函数
    * @param &$arr array 待排序的数组
    */
    function mergeSort(&$arr) {
        $len = count($arr);//求得数组长度
     
        mSort($arr, 0, $len-1);
    }
    /**
    * 实际实现归并排序的程序
    * @param &$arr array 需要排序的数组
    * @param $left int 子序列的左下标值
    * @param $right int 子序列的右下标值
    */
    function mSort(&$arr, $left, $right) {
     
        if($left < $right) {
            //说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
            //计算拆分的位置,长度/2 去整
            $center = floor(($left+$right) / 2);
            //递归调用对左边进行再次排序:
            mSort($arr, $left, $center);
            //递归调用对右边进行再次排序
            mSort($arr, $center+1, $right);
            //合并排序结果
            mergeArray($arr, $left, $center, $right);
        }
    }
     
    /**
    * 将两个有序数组合并成一个有序数组
    * @param &$arr, 待排序的所有元素
    * @param $left, 排序子数组A的开始下标
    * @param $center, 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
    * @param $right, 排序子数组B的结束下标(开始为$center+1)
    */
    function mergeArray(&$arr, $left, $center, $right) {
        //设置两个起始位置标记
        $a_i = $left;
        $b_i = $center+1;
        while($a_i<=$center && $b_i<=$right) {
            //当数组A和数组B都没有越界时
            if($arr[$a_i] < $arr[$b_i]) {
                $temp[] = $arr[$a_i++];
            } else {
                $temp[] = $arr[$b_i++];
            }
        }
        //判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
        while($a_i <= $center) {
            $temp[] = $arr[$a_i++];
        }
        //判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
        while($b_i <= $right) {
            $temp[] = $arr[$b_i++];
        }
     
        //将$arrC内排序好的部分,写入到$arr内:
        for($i=0, $len=count($temp); $i<$len; $i++) {
            $arr[$left+$i] = $temp[$i];
        }
     
    }
     
     
    //do some test:
    $arr = array(4, 7, 6, 3, 9, 5, 8);
    mergeSort($arr);
    print_r($arr);
    

      参考资料:http://blog.phpha.com/archives/1683.html

    四、堆排序

      主要思想:

      堆积排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

         (堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素 )

    节点与数组索引关系

    对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约

       代码实现:

    /**
     * 使用异或交换2个值,原理:一个值经过同一个值的2次异或后,原值不变
     * @param int $a
     * @param int $b
     */
    function swap(&$a,&$b){
        $a = $a^$b;
        $b = $a^$b;
        $a = $a^$b;
    }
     
    /**
     * 整理当前树节点($n),临界点$last之后为已排序好的元素
     * @param int $n
     * @param int $last
     * @param array $arr
     * 
     */
    function adjustNode($n,$last,&$arr){
        $l = $n<<1;   // 左孩子
        if( !isset($arr[$l])||$l>$last ){
            return ;
        }
        $r = $l+1;  // 右孩子
        // 如果右孩子比左孩子大,则让父节点与右孩子比
        if( $r<=$last&&$arr[$r]>$arr[$l] ){
            $l = $r;
        }
        // 如果其中子节点$l比父节点$n大,则与父节点$n交换
        if( $arr[$l]>$arr[$n] ){
            swap($arr[$l],$arr[$n]);
            // 交换之后,父节点($n)的值可能还小于原子节点($l)的子节点的值,所以还需对原子节点($l)的子节点进行调整,用递归实现
            adjustNode($l, $last, $arr);
        }
    }
     
    /**
     * 堆排序(最大堆)
     * @param array $arr
     */
    function heapSort(&$arr){
        // 最后一个算数位
        $last = count($arr);
        // 堆排序中常忽略$arr[0]
        array_unshift($arr, 0);
        // 最后一个非叶子节点
        $i = $last>>1;
        // 整理成最大堆,最大的数放到最顶,并将最大数和堆尾交换,并在之后的计算中,忽略数组最后端的最大数(last),直到堆顶(last=堆顶)
        while(true){
            adjustNode($i, $last, $arr);
            if( $i>1 ){
                // 移动节点指针,遍历所有节点
                $i--;
            }
            else{
                // 临界点$last=1,即所有排序完成
                if( $last==1 ){
                    break;
                }
                swap($arr[$last],$arr[1]);
                $last--;
            }
        }
        // 弹出第一个元素
        array_shift($arr);
    }
    

      参考资料:http://www.cnblogs.com/iampeter/p/3223487.html

    五、选择排序

      主要思想:

      1. 首先在未排序序列中找到最小元素,存放到排序序列的起始位置

      2. 然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾

      3. 以此类推,直到所有元素均排序完毕

      代码实现:

    function selectSort( Array $arr){
        $len = count($arr);
        for( $i = 0; $i < $len ; $i ++){
            for($j = $i; $j < $len ; $j ++){
                if( $arr[$i] > $arr[$j]){
                    $temp = $arr[$i];
                    $arr[$i] = $arr[$j];
                    $arr[$j] = $temp;
                }
            }
        }
        return $arr;
    }
    
    $arr = array(23,1,45,12,7,19);
    var_dump(selectSort($arr));
    

    六、冒泡排序

      主要思想:

      1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个

      2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对;这样,最后的元素应该会是最大的数

      3. 以此类推,针对所有的元素重复以上的步骤,除了最后一个。

      代码实现:

    function bubbleSort( Array $arr){
        $len = count($arr);
        for($i = 0; $i < $len - 1; $i ++){
            for($j = 0; $j < $len - 1 - $i ; $j ++){
                if( $arr[$j] > $arr[$j+1]){
                    $temp = $arr[$j];
                    $arr[$j] = $arr[$j+1];
                    $arr[$j+1] = $temp;
                }
            }
        }
        return $arr;
    }
    $arr = array(23,1,45,12,7,19);
    var_dump(bubbleSort($arr));
    

    七、插入排序

       主要思想:

      1. 从第一个元素开始,该元素可以认为已经被排序

      2. 取出下一个元素,在已经排序的元素序列中从后向前扫描

      3. 如果该元素(已排序)大于新元素,将该元素移到下一位置

      4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

      5. 将新元素插入到该位置中

      6. 重复步骤2

      代码实现:

    function insertSort(&$arr){
        $len = count($arr);
        // 默认下标为0的是已排好序的
        for($i = 1; $i < $len ; $i ++){
            $insertValue = $arr[$i]; // 待插入数据
            $insertIndex = $i - 1;
            while($insertIndex >= 0 && $insertValue < $arr[$insertIndex]){
                // 数组后移
                $arr[$insertIndex + 1] = $arr[$insertIndex];
                $insertIndex -- ;
            }
            $arr[$insertIndex + 1] = $insertValue;
        }
    }
    $arr = array(23,1,45,12,7,19);
    insertSort($arr);
    var_dump($arr);
    

    八、希尔排序

      主要思想:

      希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。

      希尔排序的大体思路是:将一个未排序的序列分成多个组,然后在组内使用插入排序对组内序列排序。我们的分组方式是将每隔固定位置(增量)的元素分成一组。之后去调整这个间隔大小,重新分组,组内重新排序。直到分组的间隔为1,也就是所有的元素分成一组,再进行一次插入排序,这样就可以完成整个序列的排序过程。

      分组序列称之为希尔排序的增量序列,增量序列有一个非常流行的选择称之为希尔增量(希尔这个人建议的增量序列):假设序列为ht...hk hk-1 .. h1 ,排序序列的长度为N,那么ht = N除以2的商, 而hk-1 = hk 除以2的商,直到h1 = 1;
    例如如果待排序数组的长度为 10,那么序列为 5, 2, 1; 

      代码实现:

    function shellSort(&$arr) {
        $len = count($arr);
        //确定增量序列
        //php内没有整除 采用floor向下去整
        for($inc=floor($len/2); $inc>=1; $inc=floor($inc/2)) {
            //内部实现与插入排序类似
            //不过比较的元素取决于增量
            for($i=$inc; $i<$len; ++$i) {
                $tmp = $arr[$i];
                for($j=$i-$inc; $j>=0 && $tmp<$arr[$j]; $j-=$inc) {
                    $arr[$j+$inc] = $arr[$j];
                }
                $arr[$j+$inc] = $tmp;
            }
        }
    }
    $arr = array(23,1,45,12,7,19);
    shellSort($arr);
    var_dump($arr);

      参考资料:http://bbs.itcast.cn/thread-7315-1-1.html

  • 相关阅读:
    一个纯CSS下拉菜单
    【荐】DIV+CSS仿360buy京东商城导航条
    JS同一个页面布局滑动门和TAB
    很漂亮的蓝色CSS下拉菜单
    用JS已经封装好的滑动门,只需调用就可以用
    set row count
    html块元素与内联元素
    Div的内容自动换行(转载)
    xmlHTTP Status
    FF innerText(转载)
  • 原文地址:https://www.cnblogs.com/fanfan259/p/4517428.html
Copyright © 2020-2023  润新知