算法学习导图+经典排序算法PHP实现

 

周末抽时间整理下算法,完整导图可点击下面链接获取。

点我看完整算法导图

 

 

 

八种排序算法的php实现

 

代码如下 拷贝后可直接运行

先上个运行后的图

 

代码:(有的自己写的 有的根据网友整理)

<?php
/**
 * Created by PhpStorm.
 * User: 百年黄沙
 * Date: 2019/7/28/0020
 * Time: 16:21:33
 */
class Sort
{
 
 
    /**
     * 直接选择排序
     *
     * 选出剩余最小值放在左边
     * 递归
     *
     * @param $unsort
     * @return $mixed
     */
    public static function ChoiceSort($unsort)
    {
        for ($i = 0; $i < count($unsort)-1; $i++) {
            $min = $i;
            for ($j = $i+1; $j < count($unsort); $j++){
                if ($unsort[$j] < $unsort[$min]) {
                    $min = $j;
                }
            }
            //最小值
            if ($min !== $i) {
                Sort::swap($unsort, $min, $i);
            }
            Sort::halt($unsort, $unsort, $i+1);
        }
        return $unsort;
    }
 
    /**
     * 选择排序类 - 堆排序 这个有点难理解 可先看其他的
     * 
     * 利用最大堆的堆顶记录的是最大关键字这一特性,每一轮取堆顶元素放入有序区,
     * 就类似选择排序每一轮选择一个最大值放入有序区,可以把堆排序看成是选择排序的改进。
     * @param $unsort
     * @return array
     */
    public static function HeapSort(&$arr)
    {
        $unsort = $arr;
        $count = count($arr);
        // 建堆 (下标小于或等于floor($count/2)-1的节点都是要调整的节点)
        for ($i = floor($count / 2) - 1; $i >= 0; $i--) {
            Sort::CreateHeap($arr, $i, $count);
        }
 
        // 调整堆
        for ($i = $count - 1; $i >= 0; $i--) {
            //将堆顶元素与最后一个元素交换
            Sort::swap($arr, 0, $i);
            Sort::CreateHeap($arr, 0, $i - 1);
            Sort::halt($unsort,$arr,17-$i);
        }
 
    }
 
    //建立堆
    public static function CreateHeap(&$arr, $start, $end)
    {
        $temp = $arr[$start];
        //沿关键字较大的孩子节点向下筛选,这里数组开始下标识0
        for ($j = 2 * $start + 1; $j <= $end; $j = 2 * $j + 1) {
            if ($j != $end && $arr[$j] < $arr[$j + 1]) {
                $j++;
            }
            if ($temp < $arr[$j]) {
                //将根节点设置为子节点的较大值
                $arr[$start] = $arr[$j];
                $start = $j;
            }
        }
        $arr[$start] = $temp;
    }
 
 
    /**
     * 插入类-直接插入排序
     *
     * 从第一个元素开始,该元素可以认为已经排好序,
     * 取下一个,在已经排好序的序列中向前扫描,
     * 有元素大于这个新元素,将已经在排好序中的元素移到下一个位置,
     * 依次执行
     *
     * @param $unsort
     * @return array
     */
    public static function InsertSort($unsort)
    {
        $sort = array();
        $len = count($unsort);
        $sort[0] = $unsort[0];
        for ($i = 1; $i < $len - 1; $i++) {
            $sort[$i] = $unsort[$i];
            for ($j = $i; $j > 0; $j--) {
                if ($sort[$j] < $sort[$j - 1]) {
                    Sort::swap($sort, $j, $j - 1);
                }
            }
            Sort::halt($unsort,$sort,$i);
        }
        return $sort;
    }
 
 
    /**
     * 插入类-shell排序
     * @param $unsort
     * @return array
     */
    public static function ShellSort($unsort)
    {
        $count = count($unsort);
        $inc = $count;  //增量
        do {
            //计算增量
            //$inc = floor($inc / 3) + 1;
            $inc = ceil($inc / 2);
            for ($i = $inc; $i < $count; $i++) {
                $temp = $unsort[$i];  //设置哨兵
                //需将$temp插入有序增量子表
                for ($j = $i - $inc; $j >= 0 && $unsort[$j + $inc] < $unsort[$j]; $j -= $inc) {
                    $unsort[$j + $inc] = $unsort[$j]; //记录后移
                }
                //插入
                $unsort[$j + $inc] = $temp;
            }
            //增量为1时停止循环
        } while ($inc > 1);
        return $unsort;
    }
 
    /**
     * 交换排序 - 冒泡排序
     *
     * 重复地走访过要排序的元素列,一次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。
     * 走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。
     * @param array $unsort
     * @return array
     */
    public static function BubbleSort(array $unsort)
    {
        $sort = $unsort;
        $len = count($unsort);
        for ($i = 0; $i < $len - 1; $i++) {
            for ($j = 1; $j < $len; $j++) {
                if ($sort[$j] < $sort[$j - 1]) {
                    Sort::swap($sort, $j, $j - 1);
                }
            }
            Sort::halt($unsort, $sort, $i + 1);
        }
        return $sort;
    }
 
    /**
     * 交换排序 - 快速排序
     *
     *  通过设置一个初始中间值,来将需要排序的数组分成3部分,
     *  小于中间值的左边,中间值,大于中间值的右边,
     *  继续递归用相同的方式来排序左边和右边,最后合并数组
     *
     * @param array $unsort
     * @return array
     */
    public static function FastSort($unsort)
    {
        $len = count($unsort);
        if ($len <= 1) {
            return $unsort;
        }
        $middle = $unsort[0]; //取中间标尺
        $left = array();
        $right = array();
 
        //todo 0 已被选做middle 注意
        for ($i = 1; $i < $len; $i++) {
            if ($unsort[$i] < $middle) {
                $left[] = $unsort[$i];
            } else {
                $right[] = $unsort[$i];
            }
        }
        $left = Sort::FastSort($left);
        $right = Sort::FastSort($right);
        return array_merge($left, array($middle), $right);
    }
 
    /**
     * 归并排序  这个好像有点问题
     *
     *  把序列分成元素尽可能相等的两半。
     *  把两半元素分别进行排序。
     *  把两个有序表合并成一个。
     *
     * @param $unsort
     * @return array
     */
    public static function MergeSort($unsort)
    {
        $len = count($unsort);
        if($len<=1){
            return $unsort;
        }
        $divide = intval($len / 2);
        $left_array = Sort::MergeSort( array_slice($unsort, 0, $divide));
        $right_array = Sort::MergeSort( array_slice($unsort, $divide, $len - $divide));

        $sort = [];
        while (count($left_array) && count($right_array)){
            $sort[] = $left_array[0] < $right_array[0] ? array_shift($left_array): array_shift($right_array);
        }
        return array_merge($sort,$left_array,$right_array);
    }

 
    /**
     * 桶排序
     *
     * 桶排序的原理是先安排N+1个桶作为容器,若数据范围为N的话。
     * 然后将测试数据(所需排序的数据)进行循环,放入对应的桶内。数据一定是在范围N内的。
     * 最后,循环桶里的元素,并且输出,进行从大到小或从小到大的排序。
     *
     *  浪费空间
     *  无法比较浮点数值
     *
     * @param $usort
     * @return array
     */
    public static function BucketSort($unsort)
    {
        //取出值的范围
        $len = max($unsort);
        //设置默认数组,默认值为0;
        for ($i = 0; $i <= $len; $i++) {
            $sort[$i] = 0;
        }
        for ($j = 0; $j < count($unsort); $j++) {
            $sort[$unsort[$j]]++;
        }
        foreach ($sort as $k => $v) {
            if (!empty($v)) {
                $arr[] = $k;
            }
        }
        return $arr;
    }
 
    /**
     * 公共交换位置方法
     * @param array $arr 待换数据
     * @param $a 位置1
     * @param $b 位置2
     */
    public static function swap(array &$arr, $a, $b)
    {
        $temp = $arr[$a];
        $arr[$a] = $arr[$b];
        $arr[$b] = $temp;
    }
 
    /**
     * 优化显示
     * @param $unsort
     * @param $arr
     * @param $i
     */
    public static function halt($unsort, $arr, $i)
    {
        if ($i == 1) {
            echo "待 处 理 :" . '[' . implode(" ", $unsort) . ']' . PHP_EOL;
        }
        echo "第" . $i . "次处理:" . '[' . implode(" ", $arr) . ']' . PHP_EOL;
    }
 
}
 
$uns = [14, 7, 23, 98, 43, 6, 8, 22];
$uns = [200, 13, 42, 34, 56, 23, 67, 365, 400, 54, 68, 3, 574, 5345, 645, 56778, 8978];
 
 
//选择排序
// print_r(Sort::ChoiceSort($uns));
 
//堆排序
//print_r(Sort::HeapSort($uns));
 
//插入排序
// print_r(Sort::InsertSort($uns));
 
//shell 排序
// print_r(Sort::ShellSort($uns));
 
//冒泡排序
// print_r(Sort::BubbleSort($uns));
 
//快速排序
// print_r(Sort::FastSort($uns));
 
//归并排序
print_r(Sort::MergeSort($uns));
 
//桶排序
// print_r(Sort::BucketSort($uns));

 

 

持续更新

posted @ 2019-07-29 00:06  阿飞afei  阅读(278)  评论(0编辑  收藏  举报