希尔排序---改良的直接插入排序

希尔排序是对直接插入排序的改良,也是冲破时间复杂度为O(n^2)的第一批算法之一

基本思想:将插入排序并不是一次性排完,而是分组进行插入排序。如一共有count个元素,设步长step1为count / 2, 即每走count / 2个元素分为一组,一共可以分为step1组,分别对每一组进行插入排序,得到新数组;此时缩短步长为step2=step1/2=count/2/2,每走step2个元素分为一组,一共可以分为step2个组,然后分别对每一组进行排序,得到新数组;此时缩短步长为step3 = step2 / 2 = count / 2 / 2 / 2......直至步长为1,在最后对所有元素进行插入排序进行微调,下面是带图详解

对于直接插入排序不懂可以看之前的博客https://blog.csdn.net/szy2333/article/details/83118677

一个数组,共有count个元素(如下图,图是偷的哈哈)

那么,初始步长为step = count / 2 = 5; 即步长为5,意思是每隔5步分为一组,一共有5组

分别对这五组元素进行排序,得到的结果为 3   5   1   6   0    8   9   4   7   2,并将步长缩短为step = step / 2 = 2;

此时步长为2,即每走两步得到的元素为一组,共分为2组

对这2组的元素分别进行插入排序,得到结果为 0   2   1   4   3   5   7   6   9   8,并将步长缩短为step = step / 2 = 1;此时步长为1,即所有元素为一个组

再对这些元素进行插入排序,得到最后的结果~

代码实现:

package BetterSort;

import java.util.Scanner;

public class ShellSort {   //是改良的直接插入排序
    public static void main(String[] args) {
        Scanner sc= new Scanner(System.in);
        int array[] = new int[10];    //定义一个数组
        System.out.println("请输入要排序的数:");
        for(int index = 0; index < 10; index++) {  //用一个循环控制数组的元素输入
            int i = sc.nextInt();
            array[index] = i;
        }

        shellSort(array);
        printArray(array);
    }

    public static void shellSort(int[] array) {
        //设定初始步长,且当步长大于零时,每次循环将步长缩减为step/2
        for(int step = array.length / 2; step > 0; step /= 2) {
            //设定数组的初始下标为0,且每走step步得到的元素分为一组,并对这组数进行插入排序
            //startIndex++是初始下标为1,然后继续每走step步得到的元素分为一组,并对这组数进行插入排序
            //直至下标为step-1时,遍历完本次所有组的元素,并返回上层循环,改变步长
            for(int startIndex = 0; startIndex < step; startIndex++) {
                insertSort(startIndex, array, step);
            }
        }
    }

    //插入排序
    public static void insertSort(int startIndex, int[] array, int step) { 
        int i = 0;
        int j = 0;
        int t = 0;
        for(i = startIndex + step; i < array.length; i += step) {  //从下标为startIndex + step的第二个元素开始遍历
            int tmp = array[i];  //建立临时变量,存储需要插入的元素值
            for(j = startIndex; j < i && tmp >= array[j]; j += step) {  //找到应该插入的位置
            }

            for(t = i; t > j; t -= step) {  //将插入位置后面的元素后移一位
                array[t] = array[t - step];
            }

            array[j] = tmp;   //将元素值插入最终位置
        }
    }



    public static void printArray(int[] array) {  //打印数组元素的方法
        for(int i = 0; i < array.length; i++) {
            System.out.print(array[i] + "  ");
        }
        System.out.print("\n");
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值