zoukankan      html  css  js  c++  java
  • 数据结构与算法排序(七)希尔排序(Shell Sort)

    摘要

    看希尔排序需要先想象出一个二维的矩阵,在这个矩阵中,有多少列数据全看步长(一定的规则得到)。处理完之后,就再接着用另一个步长组成矩阵处理。直到步长全部使用完。

    这里的巧妙之处就是没有把序列先处理成二维数组,而是通过与步长配合,依旧在一维的序列中处理。

    逻辑

    希尔排序相当于把序列当作一个矩阵,逐列进行排序。当全部排序完成,整个序列就完全有序

    矩阵的列数取决于步长序列

    流程

    1. 创建步长序列
    2. 从最大步长开始,整列排序,直到排序完成

    实现

    创建步长序列,这里是有一个数组存放步长数据。步长是序列的长度减半直到步长为0 结束。这里必定会有步长是 1 的数据,所以不用担心序列没有完全排序完。

    List<Integer> shellStepSequence() {
    	List<Integer> stepSequence = new ArrayList<>();
    	int step = array.length;
    	while ((step >>= 1) > 0) {
    		stepSequence.add(step);
    	}
    	return stepSequence;
    }
    

    按照步长序列遍历,序列就会按照不同的步长去处理排序。然后通过不断地缩小步长来使得序列逐渐成为一维的序列。

    	List<Integer> stepSequence = shellStepSequence();
    	for (Integer step : stepSequence) {
    		sort(step);
    	}
    

    把每一列进行排序。数组中的索引是 col+row*step。这个地方就是巧妙的地方了,通过 col+row*step 来处理每一列中的元素比较排序处理。用这种方式就相当于把一个一维数组给拆分成每一行最多有 step 的元素的多列序列,即二维数组。

    而这里的巧妙就是,给我们营造了一个二维序列的空间,实际的比较和交换逻辑还是在一维数组上进行,不用额外创造空间,这样的逻辑,真的是牛。

    /*
     * 分成 step 列进行排序
     */
    void sort(int step) {
    	// col: 第几列
    	for (int col = 0; col < step; col++) {
    		// 对第 col 列进行排序
    		// 对 [0, array.length) 进行插入排序
    		for (int begin = col + step; begin < array.length; begin+=step) {
    			int cur = begin;
    			while (cur > col && cmp(cur, cur - step) < 0) {
    				swap(cur, cur - step);
    				cur -= step;
    			}
    		}
    	}
    }
    

    时间和空间复杂度

    • 最好、平均时间复杂度:O(1)
    • 最坏时间复杂度:O(n^2)
    • 空间复杂度:O(1)
    • 属于不稳定排序
  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/shsuper/p/15154223.html
Copyright © 2011-2022 走看看