java希尔排序

java希尔排序

1、基本思想:

希尔排序也成为“缩小增量排序”,其基本原理是,现将待排序的数组元素分成多个子序列,使得每个子序列的元素个数相对较少,然后对各个子序列分别进行直接插入排序,待整个待排序列“基本有序”后,最后在对所有元素进行一次直接插入排序。因此,我们要采用跳跃分割的策略:将相距某个“增量”的记录组成一个子序列,这样才能保证在子序列内分别进行直接插入排序后得到的结果是基本有序而不是局部有序。希尔排序是对直接插入排序算法的优化和升级。 
所谓的基本有序,就是小的关键字基本在前面,大的基本在后面,不大不小的基本在中间,例如{2,1,3,6,4,7,5,8,9,}就可以称为基本有序了。但像{1,5,9,3,7,8,2,4,6}这样,9在第三位,2在倒数第三位就谈不上基本有序。

2、复杂度分析:

希尔排序的关键并不是随便分组后各自排序,而是将相隔某个“增量”的记录组成一个子序列,实现跳跃式移动,使得排序的效率提高。需要注意的是,增量序列的最后一个增量值必须等于1才行。另外,由于记录是跳跃式的移动,希尔排序并不是一种稳定的排序算法。 
希尔排序最好时间复杂度和平均时间复杂度都是这里写图片描述,最坏时间复杂度为这里写图片描述。//最好情况即不需要交换数据

3、排序过程如下:

以数组{26, 53, 67, 48, 57, 13, 48, 32, 60, 50 }为例,步长序列为{5,2,1} 
初始化关键字: [26, 53, 67, 48, 57, 13, 48, 32, 60, 50 ]

这里写图片描述

最后的排序结果: 
13 26 32 48 48 50 53 57 60 67

4、算法分析:

先从array[0]开始,以incrementNum为增量的进行直接插入排序,直到数组末尾,然后从array[1]开始重复:以incrementNum为增量的进行直接插入排序; 然后从array[1]开始重复......一直到array[n]。

    然后取一个小于上一步增量的新的增量(比如设置为incrementNum/2),对前一个步骤的结果array进行遍历,直接插入排序....

    再取小于上一步增量的新的增量,重复进行:遍历,直接插入排序

    直到新的增量小于1之后再退出循环

比如现在有数组{82 ,31 ,29 ,71, 72, 42, 64, 5,110}   第一次取增量设置为array.length/2 = 4    先从82开始以4为增量遍历直到末尾,得到(82,42) 排序得到{42 ,31 ,29 ,71, 72, 82, 64, 5,110}。 然后从第二个数31开始重复上一个步骤,得到(31,64) 排序得到{42 ,31 ,29 ,71, 72, 82, 64, 5,110}.......   以4为增量的遍历完数组之后,得到的结果是{42,31,5,71,72,82,64,29,110}

   然后重新区增量,这儿设定为incrementNum/2 = 2,对{42 ,31,5,71,72,82,64,29,110}重复步骤1。  完事之后,在取新的增量,重复步骤1。 直到取到的增量小于1,退出循环。

比如有这么一种情况:对一个无序数组进行从小到大的排序,但是数组的最后一个位置的数是最小的,我们要把它挪到第一个位置,其他位置的都要往后移动,要是这个数组非常大,那么直接插入排序的开销就非常大。

5、代码示例:

package sort;

import java.util.Arrays;

/**
 * 希尔排序
 * 
 * @author TangJiang 2017年11月24日 下午4:51:37
 *
 */
public class ShellSort {
    public static void ShellSortTest(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        // 设置初始增量
        int increase = arr.length / 2;
        while (increase >= 1) {
            for (int i = 0; i < arr.length; i++) {
                // 进行跳跃插入排序
                for (int j = i; j < arr.length - increase; j = j + increase) {
                    // 比较大小交换数据
                    if (arr[j] > arr[j + increase]) {
                        int temp = arr[j];
                        arr[j] = arr[j + increase];
                        arr[j + increase] = temp;
                    }
                }
            }
            // 设置新的增量
            increase = increase / 2;
        }
    }

    public static void main(String[] args) {
        int[] a = { -1, 3, 6, 2, 6, 89, 3 };
        ShellSortTest(a);
//        for (int i : a) {
//            System.out.println(i + "");
//        }
        System.out.println(Arrays.toString(a));
    }
}
原文地址:https://www.cnblogs.com/tangjiang-code/p/7891581.html