六、飞梭排序算法:
飞梭排序是冒泡排序的轻微变形。不同的地方在于,飞梭排序是从低到高然后从高到低来回排序,而冒泡排序则仅从低到高去比较序列里的每个元素。
先对数组从左到右进行冒泡排序(升序),则最大的元素去到最右端;再对数组从右到左进行冒泡排序(降序),则最小的元素去到最左端;以此类推,依次改变冒泡的方向,并不断缩小未排序元素的范围,直到最后一个元素结束。
飞梭排序算法源码:
- /**
- * ShuttleSort
- *
- * @param array $data
- * @return array
- */
- function ShuttleSort(array $data)
- {
- /**
- * 替换方法
- *
- * @param array $data
- * @param $i
- * @param $j
- * @return array
- */
- $swap = function (array &$data, $i, $j) {
- $temp = $data[$i];
- $data[$i] = $data[$j];
- $data[$j] = $temp;
- return $data;
- };
- $count = count($data);
- $left = 0;
- $right = $count - 1;
- while ($left < $right) {
- // 从左到右
- $lastRight = 0;
- for ($i = $left; $i < $right; $i++) {
- if ($data[$i] > $data[$i + 1]) {
- $swap($data, $i, 1 + $i);
- $lastRight = $i;
- }
- }
- $right = $lastRight;
- // 从右到左
- $lastLeft = 0;
- for ($j = $right; $left < $j; $j--) {
- if ($data[$j - 1] > $data[$j]) {
- $swap($data, $j - 1, $j);
- $lastLeft = $j;
- }
- }
- $left = $lastLeft;
- }
- return $data;
- }
七、希尔排序算法:
希尔排序是基于插入排序的,区别在于插入排序是相邻的一个个比较(类似于希尔中h=1的情形),而希尔排序是距离h的比较和替换。
希尔排序中一个常数因子n,原数组被分成各个小组,每个小组由h个元素组成,很可能会有多余的元素。当然每次循环的时候,h也是递减的(h=h/n)。第一次循环就是从下标为h开始。希尔排序的一个思想就是,分成小组去排序。
希尔排序算法源码:
- /**
- * ShellSort
- *
- * @param array $container
- * @return array
- */
- function ShellSort(array $container)
- {
- $count = count($container);
- for ($increment = intval($count / 2); $increment > 0; $increment = intval($increment / 2)) {
- for ($i = $increment; $i < $count; $i++) {
- $temp = $container[$i];
- for ($j = $i; $j >= $increment; $j -= $increment) {
- if ($temp < $container[$j - $increment]) {
- $container[$j] = $container[$j - $increment];
- } else {
- break;
- }
- }
- $container[$j] = $temp;
- }
- }
- return $container;
- }
八、归并排序算法:
归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
实现思路:
比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素b[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
归并排序算法源码:
- class MergeSort
- {
- /**
- * MergeSort constructor.
- * 是开始递归函数的一个驱动函数
- *
- * @param array $arr 待排序的数组
- */
- public function __construct(array $arr)
- {
- $this->mSort($arr, 0, count($arr) - 1);
- var_dump($arr);
- }
- /**
- * 实际实现归并排序的程序
- *
- * @param $arr array 需要排序的数组
- * @param $left int 子序列的左下标值
- * @param $right int 子序列的右下标值
- */
- public function mSort(&$arr, $left, $right)
- {
- if ($left < $right) {
- //说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
- //计算拆分的位置,长度/2 去整
- $center = floor(($left + $right) / 2);
- //递归调用对左边进行再次排序:
- $this->mSort($arr, $left, $center);
- //递归调用对右边进行再次排序
- $this->mSort($arr, $center + 1, $right);
- //合并排序结果
- $this->mergeArray($arr, $left, $center, $right);
- }
- }
- /**
- * 将两个有序数组合并成一个有序数组
- *
- * @param &$arr , 待排序的所有元素
- * @param $left , 排序子数组A的开始下标
- * @param $center , 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
- * @param $right , 排序子数组B的结束下标(开始为$center+1)
- */
- public function mergeArray(&$arr, $left, $center, $right)
- {
- echo '| ' . $left . ' - ' . $center . ' - ' . $right . ' - ' . implode(',', $arr) . PHP_EOL;
- //设置两个起始位置标记
- $a_i = $left;
- $b_i = $center + 1;
- $temp = [];
- 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 ];
- }
- }
- }
以上算法由波波收集整理自网络,全部由PHP实现,旨在为喜欢PHP语言的朋友提供一些算法研究的帮助。欢迎大家收藏!