图文并茂!一文教你掌握十大排序算法之希尔排序(增量排序)

如果还没真正了解过直接插入排序的读者可先去看看直接插入排序的原理及实现:一文掌握直接插入排序

1. 希尔排序原理介绍

希尔排序是直接插入排序的一种更高效的改进版本。但是希尔排序是一种非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  1. 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  2. 插入排序一般来说是非常低效的,因为插入排序每次只能将数据移动一位;

希尔排序的原理:将一个待排序的数组分为若干个以Step为增量的若干个子序列,对这若干个子序列依次进行直接插入排序,在每一次排序完以后的Step呈递减趋势变化,当Step为1时,此时的序列已经基本有序,对整个序列进行直接插入排序。当增量为0时代表数组已经有序。

2. 算法流程演示:

以下图为例:待排序数组为:[3, 5, 1, 2, 4, 6, 7]

1. 增量Step取数组长度的一半即 7 / 2 = 3,意思就是每3个增量的元素被视为同一个序列当中

(我们主观逻辑上的序列,本质上还是只有一个数组)

(index = 0,index = 3, index = 6)三个元素组成一个序列:[3, 2, 7]

(index = 1,index = 4,index = 7(超出数组长度))的两个元素组成一个序列:[5, 4]

(index = 2,index = 5)的两个元素组成一个序列:[1, 6]

我们对这三个序列进行直接插入排序,排序完成后各个子序列的状态是:[2, 3, 7],[4, 5],[1, 6]

从原序列来看,排序后的序列为:[2, 4, 1, 3, 5, 6, 7],此时看到数组已经大致有序了,较大的数都在数组靠右的位置,较小的数都在数组靠左的位置。

2. 增量以原来的1/2递减,即Step = Step >> 1 = 3 >> 1 = 1,此时增量为1,待排序的序列为整个数组序列[2, 4, 1, 3, 5, 6, 7]

使用直接插入排序对整个序列进行排序,具体流程就不演示了,我们可以发现只需要移动三次就可以完成排序了,分别是1和4交换位置,1和2交换位置,3和4交换位置,希尔排序在面对数据量较大的数组时表现出来的速度会比直接插入排序快很多。

3. Step >> 1 = 0,表明数组已有序,排序完成。

3. 代码实现

/**
 * @author Zeng
 * @date 2020/2/29 23:04
 */
public class 希尔排序1 {

    public static void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void shellSort(int[] arr){
        int step = arr.length / 2;
        while (step != 0){
            System.out.print("增量为:"+step+";");
            System.out.print("数组的子序列分为:");
            for (int i = 0; i < step; i++){
                System.out.print("{ ");
                for (int j = i; j < arr.length; j+=step){
                    System.out.print(arr[j]+" ");
                }
                System.out.print("};");
            }
            //核心算法,本质上是直接插入排序
            for (int i = 0; i < step; i++){
                int index = i + step;
                while (index < arr.length){
                    int current = arr[index];
                    int position = index - step;
                    while (position >= 0 && arr[position] > current){
                        swap(arr, position, position + step);
                        position -= step;
                    }
                    index += step;
                }
            }
            step = step >> 1;
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{3, 5, 1, 2, 4, 6, 7};
        shellSort(arr);
        System.out.print("排序结果:");
        for (int i : arr) {
            System.out.print(i+" ");
        }
    }

}
//增量为:3;数组的子序列分为:{ 3 2 7 };{ 5 4 };{ 1 6 };
//增量为:1;数组的子序列分为:{ 2 4 1 3 5 6 7 };
//排序结果:1 2 3 4 5 6 7 
发布了50 篇原创文章 · 获赞 46 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41949328/article/details/104585092