• 希尔排序


    希尔排序

    希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n^2)的第一批算法之一

    基本思想

    希尔排序的基本思想是:现将待排序的数组分成多个待排序的子序列,使得每个子序列的元素较少,然后对各个子序列分别进行插入排序,待到整个待排序的序列基本有序的时候,最后在对所有的元素进行一次插入排序。
    希尔排序的具体步骤如下:

    • 选择一个步长序列t1,t2,t3,···,tk, 满足tm>tn(m < n), tk = 1
    • 按照步长序列个数,对待排序序列进行k趟排序
    • 每趟排序根据对应的步长,将待排序序列分割成若干个子序列,分别对这些子序列进行插入排序

    我们选择的步长是一个缩小增量序列,通常情况下选择的步长为gap=length/2,缩小增量继续以gap=gap/2的方式,直到增量最后变成1,即{n/2,(n/2)/2...1}。希尔排序的增量序列的选择是一个数学难题,通常选取这个常用的增量序列。下图示例了希尔排序的过程:
    shell_sort

    代码实现

    /**
     * ShellSort
     */
    import java.util.Arrays;
    public class ShellSort {
        /**
         *  希尔排序 针对有序序列在插入时采用交换法
         */
        public static void shellSort(int[] array) {
            int len = array.length;
            if (len <= 0) {
                return;
            }
            //初始化步长
            int gap = len>>1;
            //循环控制缩小步长
            for (; gap >= 1; gap >>= 1) {
                //从第gap个元素,逐个对其所在组的元素进行插入排序
                for (int i = gap; i < len; i++) {
                    int j = i;
                    while (j-gap>=0 && array[j] < array[j-gap]) {
                        swap(array, j, j-gap);
                        j -= gap;
                    }
                }
            }
        }
    
        /**
         *  希尔排序 针对有序序列在插入时采用移动法
         */
        public static void shellSortS(int[] array) {
            int len = array.length;
            if (len <= 0) {
                return;
            }
            int gap = len>>1;
            for (; gap >= 1; gap >>= 1) {
                for (int i = gap; i < len; i++) {
                    int j = i;
                    int tmp = array[j];
                    while (j-gap>=0 && array[j] < array[j-gap]) {
                        array[j] = array[j-gap];
                        j -= gap;
                    }
                    array[j] = tmp;
                }
            }
        }
        public static void swap(int[] array, int pos1, int pos2){
            int tmp = array[pos1];
            array[pos1] = array[pos2];
            array[pos2] = tmp;
        }
    
        
        public static void main(String []args){
            int []arr ={1,4,2,7,9,8,3,6};
            shellSort(arr);
            System.out.println(Arrays.toString(arr));
            int []arr1 ={1,4,2,7,9,8,3,6};
            shellSortS(arr1);
            System.out.println(Arrays.toString(arr1));
        }
    }
    

    复杂度及稳定性

    希尔排序时间复杂度
    希尔排序的时间复杂度与增量(即,步长gap)的选取有关。例如,当增量为1时,希尔排序退化成了直接插入排序,此时的时间复杂度为O(N²),而Hibbard增量{1, 3, ..., 2^k-1}的希尔排序的时间复杂度为O(N3/2)。
    希尔排序稳定性
    希尔排序是不稳定的算法,它满足稳定算法的定义。对于相同的两个数,可能由于分在不同的组中而导致它们的顺序发生变化。

    算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

  • 相关阅读:
    swiper 增加一个鼠标移入分页器的小点后就切换展示图片
    css中的单冒号和双冒号 以及 伪类和伪元素
    pointer-events: none;元素永远不会成为鼠标事件的target
    jQuery off() 方法
    jQuery方法汇总
    vue 数组修改 页面无法刷新
    mysql error Code 1441:datetime function: datetime field overflow
    生命的意义
    删除镜像或容器
    nginx Redis 不能访问问题
  • 原文地址:https://www.cnblogs.com/chailinbo/p/9288709.html
Copyright © 2020-2023  润新知