【数据结构与算法(Java)】排序-希尔排序(插入排序 - 缩小增量排序)

本文详细介绍了希尔排序的优化思路,通过不断分组并进行简单插入排序,提高排序效率。提供了两种实现方式,包括交换法和移位法,其中移位法更为高效。希尔排序是对简单插入排序的改进,尤其在处理大量数据时性能更优。
摘要由CSDN通过智能技术生成

1. 排序思路

  • 不断将原数组分组,每组进行"简单插入排序"
  • 分组方式为:
    • 第一次分 length/2 组,
    • 第二次分 length/2/2 组,
    • 第三次分 length/2/2/2 组,
    • …,
    • 以此类推,最后一次分为 1 组
  • 结束分组和分别的插入排序,整个数组的排序即完成
  • 注意:插入方法有"交换法"(效率低)和"移位法"(高效)两种
  • 另见:简单插入排序
    • “希尔排序” 是对 “简单插入排序” 的优化
    • 若出现插入数较小时,简单插入排序效率变低
    • 如 [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

2. 代码实现

    /**
     * 希尔排序(缩小增量排序)
     *      思路:
     *          - 不断将原数组分组,每组进行"简单插入排序"
     *          - 分组方式为:
     *              第一次分 length/2 组,
     *              第二次分 length/2/2 组,
     *              第三次分 length/2/2/2 组,
     *              ...,
     *              以此类推,最后一次分为 1 组
     *          - 结束分组和分别的插入排序,整个数组的排序即完成
     *          - 注意:插入方法有"交换法"(效率低)和"移位法"(高效)两种
     * @param originalArray - 原始数组
     * @return - 排序后数组(不改变原始数组)
     */
    // 交换法(低效)
    public static int[] shellSortByExchanging(int[] originalArray) {
        // 1. 复制数组
        int[] sortedArray = new int[originalArray.length];
        for (int i = 0; i < originalArray.length; i++) {
            sortedArray[i] = originalArray[i];
        }
        // 2. 大循环,每轮循环将数组分成 gap 组,gap = gap / 2
        for (int gap = sortedArray.length / 2; gap > 0; gap /= 2) {
            // 2.1 设置临时int变量,用于交换
            int tempNumber = 0;
            // 2.2 中循环和小循环,将每组用"选择排序"的方式分别排序
            for (int i = gap; i < sortedArray.length; i++) {
                for (int j = i - gap; j >= 0; j -= gap) {
                    // 若 前 > 后:交换
                    if (sortedArray[j] > sortedArray[j + gap]) {
                        tempNumber = sortedArray[j];
                        sortedArray[j] = sortedArray[j + gap];
                        sortedArray[j + gap] = tempNumber;
                    }
                }
            }
        }
        // 3. 返回排好序的数组
        return sortedArray;
    }
    
    // 优化 - 移位法(高效)
    public static int[] shellSortByShifting(int[] originalArray) {
        // 1. 复制数组
        int[] sortedArray = new int[originalArray.length];
        for (int i = 0; i < originalArray.length; i++) {
            sortedArray[i] = originalArray[i];
        }

        // 2. 大循环,每轮循环将数组分成 gap 组,gap = gap / 2
        for (int gap = sortedArray.length / 2; gap > 0; gap /= 2) {
            // 对每个组用"移位"的方式执行"插入排序"
            // 2.1 中循环,每一轮即一组,找到每组"乱序表"的首位 i (初始下标为gap)
            for (int i = gap; i < sortedArray.length; i++) {
                // (1) 设置int变量储存本轮循环要插入的位置下标;设置int变量储存要插入的数值("无序表"首位数)
                int positionForInserting = i;
                int insertNumber = sortedArray[i];
                // (2) 小循环:遍历"有序表",将"无序表"的首位与"有序表"逐个比较,寻找插入点
                // 若达到"有序表"的首位,或 待插入数值 >= positionForInserting - gap 数值(找到插入点),停止本轮小循环
                while (positionForInserting - gap >= 0 && insertNumber < sortedArray[positionForInserting - gap]) {
                    sortedArray[positionForInserting] = sortedArray[positionForInserting - gap];
                    positionForInserting -= gap;
                }
                // (3) 将 待插入数值 插入 待插入点
                sortedArray[positionForInserting] = insertNumber;
            }
        }
        // 3. 返回排好序的数组
        return sortedArray;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值