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)
    • 属于不稳定排序
  • 相关阅读:
    .hpp文件
    最小高度的BST
    检查图中的有向路径
    c++ 对象内存布局详解
    链表求差
    offer--链表反转和从尾到头打印链表
    平衡二叉树的判断
    java 抽象类和接口
    原型模式--prototype
    装饰模式decorator
  • 原文地址:https://www.cnblogs.com/shsuper/p/15154223.html
Copyright © 2011-2022 走看看