php 希尔排序算法

希尔排序

希尔排序(Shell’s Sort)是 插入排序 的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序的最好时间复杂度O(n)和最坏时间复杂度O(n2)。想要理解希尔排序,首先得理解插入排序。

希尔排序是按照增量进行分组,然后对每一组,进行插入排序,使得每一组基本有序。

图解参考:
在这里插入图片描述

以下是希尔排序的php版本

<?php
ini_set("display_errors", "On");
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2021/4/7 0007
 * Time: 下午 2:28
 *
 * 给定一个数组,内容都为数字
 * 外层循环分隔整个数组为多个长度为增量(增量为整数,每次循环除以2)的子序列
 * 外层每分隔一次,内层从增量对应的键开始循环直到数组最后一位
 * 与选择排序同理,如果 当前键位 – 增量 (也就是该子序列对应的另一个值)大于当前键位的值,插入当前键位到该子序列对应的另一个值左边(步长为增量)
 * 继续按步长为增量进行累减(当前键位 – 增量 – 增量… )直到当前键位的值大于该子序列对应的另一个值
 * 外层循环结束前已经是一个相对有序的数组了,最后一次循环步长为1,与正常选择排序相同
 * 结束外层循环,得到一个升序数组
 *
 * https://zhuanlan.zhihu.com/p/56836177
 */

function donald_shell_sort($data){

    $length = $num = count($data);
    do {
        $step = $num = intval($num/2); // step = 3
        // 划分3组,[9,1] [4,6] [2,7]
        // 对每组进行插入排序 : 将一个记录插入到已排好序的序列中,从而得到一个新的有序序列(将序列的第一个数据看成是一个有序的子序列,然后从第二个记录逐个向该有序的子序列进行有序的插入,直至整个序列有序
        for ($i = $step; $i < $length; $i++) {
            // 对第一组 [9,1]进行插入排序 ,由 9的下标0,1的下标3,
            if($data[$i] < $data[$i-$step]){ // $data[3] < $data[0]
                $min = $data[$i]; // 保存小的数(哨兵)
                // $i = 3 ,$step = 3, j=0,  相当拿 $data[0] 和 $data[3] 对比
                for($j = $i-$step; $j >= 0 && $min < $data[$j];$j -= $step){
                    // 往后排.
                    $data[$j+$step] = $data[$j ] ;
                    // 此时data = [9,9] 第一个9的下标是0,第二个下标是3(数据原来是1,被9覆盖)
                }
                // 此时 j = -1,最后将min放到最前面
                $data[$j+$step] = $min;
                // 此时data = [1,9]
                // ... 再次循环 [4,6] ... [2,7]
            }
        }

    }while ($step > 1);

    return $data;

}

//function donald_shell_sort_2($array){
//    $count_array = count($array);
//
//
//    for($i = (int)($count_array/2);$i>0;$i=(int)($i/2)){ //循环分隔整个数组为多个长度为增量(增量为整数,每次循环除以2)的子序列
//        for($j = (int)$i;$j<$count_array;$j++){ //从增量开始判断
//            $index = (int)($j - $i); //步长为增量
//            $current = $array[$j];
//            while($index >= 0 && $array[$index] > $current){ //相对选择排序只是步长为增量而不为1
//                $array[$index + $i] = $array[$index];
//                $index = $index - $i;
//            }
//            $array[$index + $i] = $current;
//        }
//    }
//
//    return $array;
//}


for ($i = 0 ; $i < 100000 ;$i ++){
    $data[] = rand(0,9999);
}
echo json_encode(donald_shell_sort($data));exit;

参考文章:
https://www.cnblogs.com/chengxiao/p/6104371.html
https://zhuanlan.zhihu.com/p/56836177

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值