• 算法学习(三):归并排序与逆序对求解


    用php实现一个归并排序算法,并基于归并排序思想求解逆序对数目。

    1. 归并排序:自顶向下

    //自顶向下归并排序:分而治之
    function mergeSortUD(&$a,$s=0,$e=null){//注意此处传引用,否则发生写时赋值
        if(!isset($e)){
            $e = count($a) - 1;
        }
        if(count($a) < 1 || $s >= $e || $s < 0 || $e >= count($a)){
            return;
        }
        $mid = $s + floor(($e - $s) / 2);//注意此处取整数,否则$mid为浮点数
        mergeSortUD($a,$s,$mid);
        mergeSortUD($a,$mid+1,$e);
        merge($a,$s,$mid,$e);
    }
    function merge(&$a,$s,$mid,$e){
        $m = [];
        $ms = 0;
        $i = $s;
        $j = $mid+1;
        while($i <= $mid && $j <= $e){
            if($a[$i] < $a[$j]){
                $m[$ms++] = $a[$i++];
            }elseif($a[$i] == $a[$j]){
                $m[$ms++] = $a[$i++];
                $m[$ms++] = $a[$j++];
            }else{
                $m[$ms++] = $a[$j++];
            }
        }
        while($i <= $mid){
            $m[$ms++] = $a[$i++];
        }
        while($j <= $e){
            $m[$ms++] = $a[$j++];
        }
        //将排好序的子区间复制到原数组
        foreach($m as $k => $v){
            $a[$s++] = $v;
        }
    }
    $a = [9,8,7,6,5,4,3,2,1,0];
    mergeSortUD($a);
    var_dump($a);

    2.归并排序:自底向上

    //自底向上归并排序:从局部到整体
    function mergeSortDU(&$a,$s=0,$e=null){
        if(!isset($e)){
            $e = count($a) - 1;
        }
        if(count($a) < 1 || $s >= $e || $s < 0 || $e >= count($a)){
            return;
        }
        
        $size = 1;
        $maxSize = count($a);
        while($size <= $maxSize){
            $i = $s;
            while($i <= $e){
                merge($a,$i,min($i+$size-1,$e),min($i+2*$size-1,$e));
                $i = $i+2*$size;
            }
            $size = $size * 2;
        }
    }
    $a = [9,8,7,6,5,4,3,2,1,0];
    mergeSortDU($a);
    var_dump($a);

    3. 求解逆序对数

    借用自顶向下归并排序的思想,每次merge逐个比较子区间元素大小时,若左子区间的元素大于右子区间元素值,则逆序对数累加。

    function rmergeSort($a,$s,$e){
        if(count($a) < 1 || $s >= $e || $s < 0 || $e >= count($a)){
            return;
        }
        $mid = $s + floor(($e - $s) / 2);//注意此处取整数,否则$mid为浮点数
        rmergeSort($a,$s,$mid);
        rmergeSort($a,$mid+1,$e);
        rmerge($a,$s,$mid,$e);
    }
    function rmerge(&$a,$s,$mid,$e){
        global $reverseCount;
        $m = [];
        $ms = 0;
        $i = $s;
        $j = $mid+1;
        while($i <= $mid && $j <= $e){
            if($a[$i] < $a[$j]){
                $m[$ms++] = $a[$i++];
            }elseif($a[$i] == $a[$j]){
                $m[$ms++] = $a[$i++];
                $m[$ms++] = $a[$j++];
            }else{
                $reverseCount++;//找到逆序对
                $m[$ms++] = $a[$j++];
            }
        }
        while($i <= $mid){
            $m[$ms++] = $a[$i++];
        }
        while($j <= $e){
            $m[$ms++] = $a[$j++];
        }
        //将排好序的子区间复制到原数组
        foreach($m as $k => $v){
            $a[$s++] = $v;
        }
    }
    $reverseCount = 0; $a = [9,8,7,6,5,4,3,2,1,0]; rmergeSort($a,0,9); var_dump($a); echo '逆序对数目:'.$reverseCount;
  • 相关阅读:
    对Promise的研究4
    对Promise的研究3
    对Promise的研究2
    对promise的研究1
    数据结构_栈
    数据结构_队列(普通队列和双端队列)
    数据结构_链表(单链表,单向循环链表,双链表)
    数据库进行参数化,查询一行或多行语句
    数据库基础应用
    选择排序
  • 原文地址:https://www.cnblogs.com/ling-diary/p/9401775.html
Copyright © 2020-2023  润新知