希爾排序算法拆解解析

前言:看了網上不少講解的,感受都不是很直觀。因此我打算用一個白話文把希爾算法講清楚。瞭解的都知道,他實際上是插入排序的改進版本。咱們都知道若是一組數據中,其局部有序數字越多,插入排序越高效。(若是有不瞭解的,能夠去了解)。知道這個特色以後,希爾算法由此而生。java

1、先讓咱們回顧下插入排序

//好比有組數據:
int[] arr = {8, 6, 2, 3, 1, 5, 7, 4};
複製代碼

文字概述: 假設第一個元素爲最小數字。那麼咱們就要從index=1開始日後循環,依次拿後面的數字,與前面的數字依次比較,找出最小數字。也就是當index =1,那就是 arr[1] 和 arr[0] 比較。當index = 2 時,就是用 arr[2] 與 arr[1] 比較得出一個最小值,而後再與 arr[0] 比較。最終完成從小到大的排序。算法

因此代碼以下數組

//{8, 6, 2, 3, 1, 5, 7, 4}
    public void inseartSort(int[] arr) {
		//因此外層循環,咱們跳過第一個元素 8,拿後面的數和前面的數比較
        for (int i = 1; i < arr.length; i++) {
			//一、這層的循環是拿後面的數和前面的【依次比較】得出最小數
            //二、下面內層循環不知道怎麼寫,咱們能夠先來拆分下邏輯
            // (1)先看外層循環,index = 1,咱們要拿arr[1]與arr[0]比較,較小的數字排在前面
            // (2)繼續看外層循環,index = 2,咱們首先要拿arr[2]和arr[1]做比較,得出最小數後,繼續和arr[0]作比較。
            // 至關於index--了。
			// (3)綜上所述:外層循環的起始點,就是內層循環的起始點,其次index--才能依次和前面的數比較,作好排序。
            // 既然是index--,那麼index要知足的條件是index > 0 。否則異常。因此代碼以下
            for (int j = i; j > 0; j--) {
                if (arr[j] < arr[j - 1]) {
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }

複製代碼

2、希爾排序

瞭解過插入排序算法的都知道。一組很長的數據裏。若是局部有序數字越多,插入排序越高效,性能越好。
希爾算法: 就是利用了這個插入排序的特色改進的。他這裏有個增量gap的概念。咱們暫且不去探討增量序列帶來的時間複雜度。markdown

假如仍是那組數據:{8, 6, 2, 3, 1, 5, 7, 4}。假設這裏的增量是 gap = arr.length/2。也就是4,他會對數組,邏輯分組成幾份(這裏也能當作,增量是幾就是分幾份),而後依次對邏輯分組裏進行插入排序,其數組仍是同一個數組。排序好以後再用 gap /= 2。也就是2。繼續邏輯分組,繼續插入排序。這樣原始數組內大部分數據都是有序數據。最後 gap = 1,對這大部分數據都是有序數據的數組進行插入排序。那麼速度就快不少,性能方便也很高效。性能

可能這麼說很籠統,請看剖析spa


2.一、gap=4 時

gap = 4時,那麼就是code

  • arr[0]和arr[4] 一組
  • arr[1]和arr[5] 一組
  • arr[2]和arr[6] 一組
  • arr[3]和arr[7] 一組
//數據就對應以下
8  6  2  3  1  5  7  4
|  |  |  |  |  |  |  |
8--|--|--|--1  |  |  |  
   6--|--|-----5  |	 |
	  2--|--------7  |
		 3-----------4
複製代碼

這樣是邏輯分組,orm

  • 8和1排序後: 1 8;
  • 5和6排序後: 5 6;
  • 2和7排序後: 2 7;
  • 3和4排序後: 3 4。
8  6  2  3  1  5  7  4
|  |  |  |  |  |  |  |
1--|--|--|--8  |  |  |  
   5--|--|-----6  |	 |
	  2--|--------7  |
		 3-----------4
複製代碼

豎着看,此時排序獲得: 1 5 2 3 8 6 7 4排序


2.二、gap = 2 時

gap爲2時就相隔2去分組,固然也就是分紅2組it

1  5  2  3  8  6  7  4
|  |  |  |  |  |  |  |
1--|--2--|--8--|--7  |  
   |     |     |     |
   |     |     |     |
   5-----3-----6-----4
複製代碼

gap=2時的分組爲

  • 1 2 8 7;排序後獲得 1 2 7 8
  • 5 3 6 4;排序後獲得 3 4 5 6

那麼就是

1  5  2  3  8  6  7  4
|  |  |  |  |  |  |  |
1--|--2--|--7--|--8  |  
   |     |     |     |
   |     |     |     |
   3-----4-----5-----6
複製代碼

豎着看,此時排序獲得: 1 3 2 4 7 5 8 6

最後gap = 1的時候就是正常的插入排序了。可能有人說,按着增量作,最後一組數據並無大部分數字有序啊。由於爲了講解選了比較少的數據size=8的數據。若是是size>=100000的話會很是的明顯。


3、希爾排序的java表達

經過上面的講解,咱們知道。其實希爾排序多了個增量的概念,大致沒有變化

首先咱們知道增量gap的變化

//不難理解,gap最終變化是4,2,1
for (int gap = arr.length / 2; gap > 0; gap /= 2) {}
複製代碼

接下來咱們把gap=1時,也就是正常插入排序的代碼直接搬進去

for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0; j--) {
                if (arr[j] < arr[j - 1]) {
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
    
    
    
   //上面式子看不大出來,咱們把它變一下以下
   //看看哪裏時候把gap加上
   for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j >= 1; j-=1) { //主要是修改了j>0 改爲了 j>=1。 j-- 改爲了 j-=1
                if (arr[j] < arr[j - 1]) {
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }




//改完以後,咱們把gap=1的狀況改爲gap。也就是把1改爲gap變化以下
        for (int gap = arr.length / 2; gap > 0; gap /= 2) {
            for (int i = gap; i < arr.length; i++) {
                for (int j = i; j >= gap; j -= gap) {
                    if (arr[j] < arr[j - gap]) {
                        int temp = arr[j - gap];
                        arr[j - gap] = arr[j];
                        arr[j] = temp;
                    }
                }
            }
        }


複製代碼

好了,希爾排序就是這樣了!接下來咱們打印下,來驗證最開始的邏輯:

相關文章
相關標籤/搜索