<?php /** * Created by PhpStorm. * User: Administrator * Date: 2020/10/28 * Time: 10:45 */ namespace App\Http\Controllers; use Illuminate\Routing\Controller as BaseController; class Sort extends BaseController { public function index() { echo "There is Sort"; echo "<br>"; echo "<pre/>"; $arr = [4, 8, 5, 7, 3, 1, 5, 6, 7, 8]; $arr = [677, 51, 24, 344, 455, 200, 576, 36, 226, 81]; print_r($arr); // $arr = $this->shell_sort($arr); //********** // $this->heap_sort($arr); // $arr = $this->radix_sort($arr); // $arr = $this->bucket_sort($arr); // $arr = $this->counting_sort($arr); // $arr = $this->insertion_sort($arr); // $arr = $this->merge_sort($arr); $this->bubble_sort($arr); // $arr = $this->selection_sort($arr); // $arr = $this->quick_sort($arr); print_r($arr); } /** * 使用异或交换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] ){ $this->swap($arr[$l],$arr[$n]); // 交换之后,父节点($n)的值可能还小于原子节点($l)的子节点的值,所以还需对原子节点($l)的子节点进行调整,用递归实现 $this->adjustNode($l, $last, $arr); } } /** * 堆排序(最大堆) * @param array $arr */ function heap_sort(&$arr) { // 最后一个蒜素位 $last = count($arr); // 堆排序中常忽略$arr[0] array_unshift($arr, 0); // 最后一个非叶子节点 $i = $last >> 1; // 整理成最大堆,最大的数放到最顶,并将最大数和堆尾交换,并在之后的计算中,忽略数组最后端的最大数(last),直到堆顶(last=堆顶) while (true) { $this->adjustNode($i, $last, $arr); if ($i > 1) { // 移动节点指针,遍历所有节点 $i--; } else { // 临界点$last=1,即所有排序完成 if ($last == 1) { break; } $this->swap($arr[$last], $arr[1]); $last--; } } // 弹出第一个元素 array_shift($arr); } function radix_sort($arr) { $max = max($arr); $count = count($arr); //创建空桶 for ($i = 0; $i < 10; $i++) { $buckets[$i] = []; } //最多几位数 $digit = 0; while ($max > 0) { $max = intval($max / 10); $digit++; } for ($j = 0; $j < $digit; $j++) { //最多几位数,就循环几轮 $ten = pow(10, $j); //取余10,100,1000... for ($k = 0; $k < $count; $k++) { //遍历被排序的数组,分别塞进10个桶里 for ($l = 0; $l < 10; $l++) { if ($arr[$k]/$ten%10 === $l) { array_push($buckets[$l], $arr[$k]); } } } $arr = []; for ($m = 0; $m < 10; $m++) { while (!empty($buckets[$m])) { array_push($arr, array_shift($buckets[$m])); } } } return $arr; } function bucket_sort($arr, $bucketSize = 5) { $count = count($arr); if ($count === 0) { return $arr; } $min = min($arr); $max = max($arr); $buckets = array(); //创建空桶 20 5 3 17/5 3 4 $bucketCount = intval(($max - $min) / $bucketSize) + 1; for ($i = 0; $i < $bucketCount; $i++) { $buckets[$i] = []; } //利用映射函数将数据分配到各个桶中 for ($j = 0; $j < $count; $j++) { array_push($buckets[intval(($arr[$j] - $min) / $bucketCount)], $arr[$j]); // array_push($buckets[ceil(($arr[$i] - $min)/$bucketSize)],$arr[$i]); } $result = []; for ($k = 0; $k < count($buckets); $k++) { //桶内排序 $buckets[$i] = $this->insertion_sort($buckets[$k]); //合并桶 $result = array_merge($result, $buckets[$i]); } return $result; } /** * Time Complexion O(n+k) */ function counting_sort($arr) { $min = min($arr); $max = max($arr); $temp = array(); $result = array(); for ($i = $min; $i <= $max; $i++) { $temp[$i] = 0; } for ($j = 0; $j < count($arr); $j++) { $temp[$arr[$j]]++; } for ($k = $min; $k < $max; $k++) { while ($temp[$k] > 0) { array_push($result, $k); $temp[$k]--; } } return $result; } /** * Time Complexion O(n²) */ public function insertion_sort($arr) { $count = count($arr); for ($i = 0; $i < $count - 1; $i++) { for ($j = $i; $j >= 0; $j--) { if ($arr[$j + 1] < $arr[$j]) { $temp = $arr[$j]; $arr[$j] = $arr[$j + 1]; $arr[$j + 1] = $temp; } } } return $arr; } /** * @param $arr * @return mixed * 654321 * 654 321 * 6 54 - * - 5 4 - * - - - 3 21 * - - - - 2 1 * 6 45 3 2 1 * 645 3 2 1 * 645 3 12 * 645 123 * 123456 */ public function merge_sort($arr) { $count = count($arr); if ($count <= 1) { return $arr; } $middle = intval($count / 2); $left = array_slice($arr, 0, $middle); $right = array_slice($arr, $middle); $left = $this->merge_sort($left); $right = $this->merge_sort($right); $output = $this->merge($left, $right); return $output; } public function merge($left, $right) { $result = array(); while (count($left) > 0 && count($right) > 0) { if ($left[0] < $right[0]) { array_push($result, array_shift($left)); } else { array_push($result, array_shift($right)); } } array_splice($result, count($result), 0, $left); array_splice($result, count($result), 0, $right); return $result; } /** * 4321 1432 1243 1234 (最小放到前面) */ public function selection_sort($arr) { $count = count($arr); for ($i = 0; $i < $count - 1; $i++) { for ($j = $i + 1; $j < $count; $j++) { if ($arr[$j] < $arr[$i]) { $temp = $arr[$j]; $arr[$j] = $arr[$i]; $arr[$i] = $temp; } } } } /** * 4321 321 4 [] * 21 3 [] * 1 2 [] * 1234 * Time Complexity O(nlogn)? */ public function quick_sort($arr) { $count = count($arr); if ($count <= 1) { return $arr; } $left = []; $right = []; $middle = $arr[0]; for ($i = 1; $i < $count; $i++) { if ($arr[$i] < $middle) { array_push($left, $arr[$i]); } else { array_push($right, $arr[$i]); } } $left = $this->quick_sort($left); $right = $this->quick_sort($right); array_push($left, $middle); $result = array_merge($left, $right); return $result; } /** * 4321 3214 2134 1234 (最大放到后面) * 从第一个依次对比相邻两个元素到arr[n],大的移到,排好最大的元素 * 从第一个依次对比相邻两个元素到arr[n-1],大的移到最后,排好最大和第二大的元素 * ... * 从第一个依次对比相邻两个元素到arr[2],大的移到 * Time Complexity O(n²) */ public function bubble_sort(&$arr) { $count = count($arr); //比较次数(count-1次) for ($i = 0; $i < $count - 1; $i++) { //第一次比较count-1次,第二次比较count-2次....第count-1次比较1次 for ($j = 1; $j < $count - $i; $j++) { if ($arr[$j - 1] > $arr[$j]) { $temp = $arr[$j - 1]; $arr[$j - 1] = $arr[$j]; $arr[$j] = $temp; } } } } }