算法学习导图+经典排序算法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));
持续更新
文字均为博主原创,转载请联系博主,谢谢!