插入排序与希尔排序

  1. 插入排序
    排序思想:从第二个元素开始,依次和该元素之前的元素比较,并使当前比较的元素之前的元素都是有序的(如何使当前元素?这里的操作和冒泡排序差不多,只不过一个向前排序,一个向后排序)。ps:其实插入排序应该与冒泡排序应该放在一起比较,插入排序是从第一个元素开始慢慢的变得有序,而冒泡排序则是从最后一个元素慢慢的变的有序。

下面简单的实现了一个插入排序的代码:

public static void main(String[] args) {
        Integer[] arr={63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5};
        System.out.println("排序前:"+JSON.toJSONString(arr));
        int totalCicle=0;
        int exchange=0;
        for(int i=1;i<arr.length;i++){
            for(int j=i-1;j>=0;j--){
                totalCicle++;
                if(arr[j+1]<arr[j]){
                    exchange++;
                    int middle=arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j]=middle;
                }
            }
            System.out.println("第"+i+"次:"+JSON.toJSONString(arr));
        }
        System.out.println("排序后:"+JSON.toJSONString(arr));
        System.out.println(totalCicle+"次循环比较");
        System.out.println(exchange+"次交换");
    }

运行程序:

排序前:[63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第1次:[1,63,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第2次:[1,2,63,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第3次:[1,2,5,63,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第4次:[1,2,5,9,63,5,25,6,4,2,6,4,2,8,6,4,2,5]
第5次:[1,2,5,5,9,63,25,6,4,2,6,4,2,8,6,4,2,5]
第6次:[1,2,5,5,9,25,63,6,4,2,6,4,2,8,6,4,2,5]
第7次:[1,2,5,5,6,9,25,63,4,2,6,4,2,8,6,4,2,5]
第8次:[1,2,4,5,5,6,9,25,63,2,6,4,2,8,6,4,2,5]
第9次:[1,2,2,4,5,5,6,9,25,63,6,4,2,8,6,4,2,5]
第10次:[1,2,2,4,5,5,6,6,9,25,63,4,2,8,6,4,2,5]
第11次:[1,2,2,4,4,5,5,6,6,9,25,63,2,8,6,4,2,5]
第12次:[1,2,2,2,4,4,5,5,6,6,9,25,63,8,6,4,2,5]
第13次:[1,2,2,2,4,4,5,5,6,6,8,9,25,63,6,4,2,5]
第14次:[1,2,2,2,4,4,5,5,6,6,6,8,9,25,63,4,2,5]
第15次:[1,2,2,2,4,4,4,5,5,6,6,6,8,9,25,63,2,5]
第16次:[1,2,2,2,2,4,4,4,5,5,6,6,6,8,9,25,63,5]
第17次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
排序后:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
153次循环比较
77次交换

分析程序运行结果,我们以63这个数为参考来看,第一次排序后,第二个元素1和第一个元素63交换了位置。第二次排序后,第三个元素2和(第一次排序后的)第二个元素63又交换了位置。第二次排序时,其实第三个元素先和第二个元素比较,发现比第二个元素小,然后第三个元素和第二个元素换位置,然后第二个元素和第一个元素又做比较,假如第二个元素比第一个元素小,那么他们继续换位置。反之则不动。后面的每次排序,都是当期排序元素开始,后一个元素和前一个元素依次比较至第一个元素,后一个元素比前一个元素小就交换位置。

到这里之后,就发现程序中有个不足的地方,就拿第3次排序来说,第3次排序排到了第四个元素5,刚开始,第四个元素5和第三个元素63比较,后一个元素5小于前一个元素63,于是5和63交换位置,然后第三个元素5(与63交换后5的位置变到第三位)又与它的前一个元素第二个元素2比较,5大于2,所以没有交换位置。到了这里,第三次排序本应结束了,因为之前说过,当前排序元素之前的元素都是有序的了,当后一个元素比前一个大时,那么此时的后一个元素就比它之前的任何元素都大,也就保证了此次排序已经有序了。但是程序并没有停止本次排序,依然用第二个元素2和1去做了一次多余的比较。如何避免这个问题呢?如果在比较时,只要发现后一个元素比前一个元素大时,我们就跳出此次循环,结果会如何呢?

public static void main(String[] args) {
        Integer[] arr={63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5};
        System.out.println("排序前:"+JSON.toJSONString(arr));
        int totalCicle=0;
        int exchange=0;
        for(int i=1;i<arr.length;i++){
            for(int j=i-1;j>=0;j--){
                totalCicle++;
                if(arr[j+1]<arr[j]){
                    exchange++;
                    int middle=arr[j+1];
                    arr[j+1]=arr[j];
                    arr[j   ]=middle;
                }else{
                    break;
                }
            }
            System.out.println("第"+i+"次:"+JSON.toJSONString(arr));
        }
        System.out.println("排序后:"+JSON.toJSONString(arr));
        System.out.println(totalCicle+"次循环");
        System.out.println(exchange+"次交换");
    }

原来的排序是后一个元素小于前一个,那么他们交换位置。先在再增加一句代码,入后后一个元素大于前一个元素,我们就跳出循环。运行结果如下:

排序前:[63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第1次:[1,63,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第2次:[1,2,63,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第3次:[1,2,5,63,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
第4次:[1,2,5,9,63,5,25,6,4,2,6,4,2,8,6,4,2,5]
第5次:[1,2,5,5,9,63,25,6,4,2,6,4,2,8,6,4,2,5]
第6次:[1,2,5,5,9,25,63,6,4,2,6,4,2,8,6,4,2,5]
第7次:[1,2,5,5,6,9,25,63,4,2,6,4,2,8,6,4,2,5]
第8次:[1,2,4,5,5,6,9,25,63,2,6,4,2,8,6,4,2,5]
第9次:[1,2,2,4,5,5,6,9,25,63,6,4,2,8,6,4,2,5]
第10次:[1,2,2,4,5,5,6,6,9,25,63,4,2,8,6,4,2,5]
第11次:[1,2,2,4,4,5,5,6,6,9,25,63,2,8,6,4,2,5]
第12次:[1,2,2,2,4,4,5,5,6,6,9,25,63,8,6,4,2,5]
第13次:[1,2,2,2,4,4,5,5,6,6,8,9,25,63,6,4,2,5]
第14次:[1,2,2,2,4,4,5,5,6,6,6,8,9,25,63,4,2,5]
第15次:[1,2,2,2,4,4,4,5,5,6,6,6,8,9,25,63,2,5]
第16次:[1,2,2,2,2,4,4,4,5,5,6,6,6,8,9,25,63,5]
第17次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
排序后:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
93次循环比较
77次交换

由运行结果可以看出来,我们改良了程序最终同样也使数组变的有序。而且性能也更优。改良前循环比较的次数为153次,改良后循环比较的次数为93次。交换次数依旧不变。可以看出来,只不过加了一句代码,程序性能的提升是显而易见的。那么,有没有更好的改良方式呢?答案是肯定的,那就是插入排序的升级版—–希尔排序。

  1. 希尔排序
    在插入排序中,往往会遇到一种极端的情况,就是当前排序的元素是该元素之前所有元素之中的最小元素,那么程序在排序时,会将这个元素与它之前的元素依次比较并交换位置。如果直接将这个最小的元素直接放到最前面,这样岂不是很完美。基于这样的考虑,一个名叫希尔的大牛便提出了一种排序算法,世人唤为希尔排序大法。

什么是希尔排序呢?官方给出的解释是:希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

我的理解是:插入排序在元素之间做比较时,是与它相邻的元素在做比较,而希尔排序呢是先跳着比较,如第一个元素直接和第n个元素比较,如果第n个元素比第一个小,那么交换位置。这个n的值就是由增量决定。这样依次第二个元素和第n+1个元素比较,直至后一个元素为最后一个元素(这个过程我称之为一次比较排序,下文中提到一次比较排序说的就是这个过程)。然后减少n的值,重复此操作,一直到n为1时,排序完成。

下面是希尔排序的简单实现

public static void main(String[] args) {
        Integer[] arr={63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5};
        System.out.println("排序前:"+JSON.toJSONString(arr));
        int totalCicle=0;
        int exchange=0;
        int h=1;
        int N=arr.length;
        int number=0;
        while(h<N/3){
            h=3*h+1;
        }
        while(h>=1){
            System.out.println("----------------h="+h+"--------------");
            for(int i=0;i<N;i++){
                for(int j=i;j>=h&&j>=0&&j-h>=0;j-=h){
                    totalCicle++;
                    if(arr[j]<arr[j-h]){
                        exchange++;
                        int middle=arr[j];
                        arr[j]=arr[j-h];
                        arr[j-h]=middle;
                    }
                    System.out.println(++number+"次:"+JSON.toJSONString(arr));
                }
            }
            h=h/3;
        }
        System.out.println("排序后:"+JSON.toJSONString(arr));
        System.out.println("循环比较次数:"+totalCicle);
        System.out.println("交换次数:"+exchange);
    }

在代码执行前,先做一波解释。通过一些资料得知,希尔排序的性能主要取决于他的增量,也就是程序中的h。那么这个h的大小到底该取多少呢?这个谁也没给出确切的定论,都是根据实际情况而定。而在上面的代码中,这个增量取的值接近数组长度。完成一次比较排序后,将h变为它的1/3,接着再一次比较排序。重复此操作,直至h为1时结束。
运行上述代码:
排序前:[63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
—————-h=13————–
1次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
2次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
3次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
4次:[8,1,2,2,9,5,25,6,4,2,6,4,2,63,6,4,5,5]
5次:[8,1,2,2,5,5,25,6,4,2,6,4,2,63,6,4,5,9]
—————-h=4————–
6次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
7次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
8次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
9次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
10次:[5,1,2,2,4,5,25,6,8,2,6,4,2,63,6,4,5,9]
11次:[4,1,2,2,5,5,25,6,8,2,6,4,2,63,6,4,5,9]
12次:[4,1,2,2,5,2,25,6,8,5,6,4,2,63,6,4,5,9]
13次:[4,1,2,2,5,2,25,6,8,5,6,4,2,63,6,4,5,9]
14次:[4,1,2,2,5,2,6,6,8,5,25,4,2,63,6,4,5,9]
15次:[4,1,2,2,5,2,6,6,8,5,25,4,2,63,6,4,5,9]
16次:[4,1,2,2,5,2,6,4,8,5,25,6,2,63,6,4,5,9]
17次:[4,1,2,2,5,2,6,4,8,5,25,6,2,63,6,4,5,9]
18次:[4,1,2,2,5,2,6,4,2,5,25,6,8,63,6,4,5,9]
19次:[4,1,2,2,2,2,6,4,5,5,25,6,8,63,6,4,5,9]
20次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
21次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
22次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
23次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
24次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
25次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
26次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
27次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
28次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
29次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
30次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
31次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
32次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
33次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
34次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
35次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
36次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
37次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
—————-h=1————–
38次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
39次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
40次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
41次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
42次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
43次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
44次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
45次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
46次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
47次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
48次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
49次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
50次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
51次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
52次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
53次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
54次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
55次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
56次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
57次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
58次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
59次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
60次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
61次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
62次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
63次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
64次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
65次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
66次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
67次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
68次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
69次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
70次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
71次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
72次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
73次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
74次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
75次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
76次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
77次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
78次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
79次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
80次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
81次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
82次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
83次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
84次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
85次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
86次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
87次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
88次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
89次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
90次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
91次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
92次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
93次:[1,2,2,2,2,4,4,5,5,6,4,6,5,9,25,6,8,63]
94次:[1,2,2,2,2,4,4,5,5,4,6,6,5,9,25,6,8,63]
95次:[1,2,2,2,2,4,4,5,4,5,6,6,5,9,25,6,8,63]
96次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
97次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
98次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
99次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
100次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
101次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
102次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
103次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
104次:[1,2,2,2,2,4,4,4,5,5,6,5,6,9,25,6,8,63]
105次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
106次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
107次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
108次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
109次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
110次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
111次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
112次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
113次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
114次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
115次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
116次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
117次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
118次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
119次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
120次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
121次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
122次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
123次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
124次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
125次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
126次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
127次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
128次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
129次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
130次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
131次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
132次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
133次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
134次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
135次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
136次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
137次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
138次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
139次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
140次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
141次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
142次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
143次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,6,25,8,63]
144次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
145次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
146次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
147次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
148次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
149次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
150次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
151次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
152次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
153次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
154次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
155次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
156次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
157次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
158次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,8,25,63]
159次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
160次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
161次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
162次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
163次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
164次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
165次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
166次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
167次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
168次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
169次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
170次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
171次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
172次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
173次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
174次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
175次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
176次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
177次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
178次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
179次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
180次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
181次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
182次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
183次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
184次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
185次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
186次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
187次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
188次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
189次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
190次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
排序后:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
循环比较次数:190
交换次数:31

排序过程分析:增量h一开始取的是13,第一次排序比较过程为第一个元素63与第十四个元素8比较,后一个8比前一个63小,两个交换位置。接着第二个元素1与第十五个元素6比较,后一个6比前一个1大,不交换位置。第五个元素与第十八个元素(数组最后一个元素)比较后,第一次比较排序完成。然后增量h变为其1/3=4.从第一个元素开始,重复上述比较排序过程,只不过这一次是第一个和第五个比较,第二个和第六个比较、、、、第n个和第n+h(n+h小于N)比较。然后再将h变为其1/3,重复操作直至h小于1为止。

通过程序输出结果来看,比较次数为190之多,二最多的在于h为1时。当h为1时,不就是插入排序了吗?那么我们能不能借鉴上面插入排序改良版的经验,来改良一下这个希尔排序呢?

public static void main(String[] args) {
        Integer[] arr={63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5};
        System.out.println("排序前:"+JSON.toJSONString(arr));
        int totalCicle=0;
        int exchange=0;
        int h=1;
        int N=arr.length;
        int number=0;
        while(h<N/3){
            h=3*h+1;
        }
        while(h>=1){
            System.out.println("----------------h="+h+"--------------");
            for(int i=0;i<N;i++){
                for(int j=i;j>=h&&j>=0&&j-h>=0;j-=h){
                    totalCicle++;
                    if(arr[j]<arr[j-h]){
                        exchange++;
                        int middle=arr[j];
                        arr[j]=arr[j-h];
                        arr[j-h]=middle;
                    }else{
                        if(h==1){
                            break;
                        }
                    }
                    System.out.println(++number+"次:"+JSON.toJSONString(arr));
                }

            }
            h=h/3;
        }
        System.out.println("排序后:"+JSON.toJSONString(arr));
        System.out.println("循环比较次数:"+totalCicle);
        System.out.println("交换次数:"+exchange);
    }

当h不为1时,我们无法保证当前排序元素之前的元素都是有序的,所以无法直接跳出内循环。当h为1时,此时的希尔排序就是一个插入排序,此时就能保证排序元素之前的元素都是有序的,所以减少无谓的比较是可以的。
改版后的程序输出结果为
排序前:[63,1,2,5,9,5,25,6,4,2,6,4,2,8,6,4,2,5]
—————-h=13————–
1次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
2次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
3次:[8,1,2,5,9,5,25,6,4,2,6,4,2,63,6,4,2,5]
4次:[8,1,2,2,9,5,25,6,4,2,6,4,2,63,6,4,5,5]
5次:[8,1,2,2,5,5,25,6,4,2,6,4,2,63,6,4,5,9]
—————-h=4————–
6次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
7次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
8次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
9次:[5,1,2,2,8,5,25,6,4,2,6,4,2,63,6,4,5,9]
10次:[5,1,2,2,4,5,25,6,8,2,6,4,2,63,6,4,5,9]
11次:[4,1,2,2,5,5,25,6,8,2,6,4,2,63,6,4,5,9]
12次:[4,1,2,2,5,2,25,6,8,5,6,4,2,63,6,4,5,9]
13次:[4,1,2,2,5,2,25,6,8,5,6,4,2,63,6,4,5,9]
14次:[4,1,2,2,5,2,6,6,8,5,25,4,2,63,6,4,5,9]
15次:[4,1,2,2,5,2,6,6,8,5,25,4,2,63,6,4,5,9]
16次:[4,1,2,2,5,2,6,4,8,5,25,6,2,63,6,4,5,9]
17次:[4,1,2,2,5,2,6,4,8,5,25,6,2,63,6,4,5,9]
18次:[4,1,2,2,5,2,6,4,2,5,25,6,8,63,6,4,5,9]
19次:[4,1,2,2,2,2,6,4,5,5,25,6,8,63,6,4,5,9]
20次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
21次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
22次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
23次:[2,1,2,2,4,2,6,4,5,5,25,6,8,63,6,4,5,9]
24次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
25次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
26次:[2,1,2,2,4,2,6,4,5,5,6,6,8,63,25,4,5,9]
27次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
28次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
29次:[2,1,2,2,4,2,6,4,5,5,6,4,8,63,25,6,5,9]
30次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
31次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
32次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
33次:[2,1,2,2,4,2,6,4,5,5,6,4,5,63,25,6,8,9]
34次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
35次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
36次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
37次:[2,1,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
—————-h=1————–
38次:[1,2,2,2,4,2,6,4,5,5,6,4,5,9,25,6,8,63]
39次:[1,2,2,2,2,4,6,4,5,5,6,4,5,9,25,6,8,63]
40次:[1,2,2,2,2,4,4,6,5,5,6,4,5,9,25,6,8,63]
41次:[1,2,2,2,2,4,4,5,6,5,6,4,5,9,25,6,8,63]
42次:[1,2,2,2,2,4,4,5,5,6,6,4,5,9,25,6,8,63]
43次:[1,2,2,2,2,4,4,5,5,6,4,6,5,9,25,6,8,63]
44次:[1,2,2,2,2,4,4,5,5,4,6,6,5,9,25,6,8,63]
45次:[1,2,2,2,2,4,4,5,4,5,6,6,5,9,25,6,8,63]
46次:[1,2,2,2,2,4,4,4,5,5,6,6,5,9,25,6,8,63]
47次:[1,2,2,2,2,4,4,4,5,5,6,5,6,9,25,6,8,63]
48次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,25,6,8,63]
49次:[1,2,2,2,2,4,4,4,5,5,5,6,6,9,6,25,8,63]
50次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,25,8,63]
51次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,9,8,25,63]
52次:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
排序后:[1,2,2,2,2,4,4,4,5,5,5,6,6,6,8,9,25,63]
循环比较次数:68
交换次数:31
这时惊喜的发现,改良效果不是一般的好啊!原因在于当h不为1时,数组已经基本上有序了,当h为1时,做了太多无用的比较。

程序排序的数组与插入排序所用的数组是同一个,通过比较可以看出,希尔排序相比较插入排序来说,不仅是交换次数还是比较次数都大大的减少了。

结语:对于算法来说,最重要的是效率。而效率是如何体现的呢,自然是执行时间。由于本例中数组长度太小,执行时间都是毫秒级别的,此时用这个来比较算法效率不具有说服力也不具有代表性。所以另辟蹊径,分析算法的执行过程,因为每个执行过程是需要时间来完成的,执行过程越多也就变相的说明了执行时间越多。

大家有更好的优化方案或者文中哪里有不对的地方欢迎大家留言指正或留言讨论!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖工-->攻城狮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值