Java 排序之插入排序、希爾排序
阿新 • • 發佈:2018-12-15
今天學習了一下 Java 陣列的相關操作,包含排序和查詢,現在先將排序記錄鞏固一下。
常用並且比較重要的幾種排序:插入排序、希爾排序、快速排序、歸併排序、氣泡排序、選擇排序。
一、插入排序
1. 插入排序演算法思想
1) 普遍思想
插入排序的演算法是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序的資料,在已排序的序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。
2) 我的理解與分析
我最初看到上面的思想,就是一臉懵逼,讀都讀不懂,又去找了很多資料,才能理解那麼一點點,所以這裡用通俗一點的話來解釋:
假設有一個數組:
int[] arr = { 22, 11, 10, 55, 44 };
- 第 0 個元素
22
看作已經排好序; - 取出第 1 個元素
11
,在已經排序的元素序列中(第一步的22
)從後向前掃描; - 如果新元素
11
比已排序的元素22
小,就把22
往後挪,並將11
插入到前面。這個時候陣列應該如下:
int[] arr = { 11, 22, 10, 55, 44 }
- 接著在取出第 2 個元素
10
,與第一個元素22
相比,如果比第一個元素小,就插入到22
之前。這個時候陣列應該如下:
int[] arr = { 11, 10, 22, 55, 44 }
10
插入後繼續與前面的元素相比,小則插入,大則不動。這個時候陣列應該如下:
int[] arr = { 10, 11, 22, 55, 44 }
- 取出第 3 個元素繼續比較…
插入排序的特點:越有序,操作的次數越少,效率越高。
2. 演算法圖解附視訊
視訊 點此檢視。
3. 演算法程式碼
import java.util.Arrays;
public class InsertSort {
public static void main(String[] args) {
int[] arr = { 11, 22, 10, 55, 44 };
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
for (int i = 1; i < arr.length; i++) { // 從第一個元素開始遍歷
for (int j = i; (j > 0) && (arr[j] < arr[j - 1]); j--) { // 條件:是否比前一個元素小,j-- 是為了挪位後再次與前一個元素比較
int temp = arr[j]; // 把移動的元素暫時存起來
arr[j] = arr[j - 1]; // 把大的元素往後挪
arr[j - 1] = temp; // 把小的元素放到前面
}
}
}
}
二、希爾排序
1. 演算法簡介
希爾排序 是插入排序的改進版本。為什麼是插入排序的改進版本呢?上面說過的插入排序,它是取出一個元素然後從後向前比較,如果小於就放到前面來,並且它的特點是 越有序,效率越高
。對於插入排序,序列資料少的話還行,要是序列資料特別多,並且是無序,那麼插入排序的效率就會很慢,所以就出現了一個希爾排序,使序列更 接近有序
,這樣的話,相對於插入排序操作資料較大的時候要快一點,不過它最終屬於插入排序類中。
2. 演算法分析
希爾排序,先將要排序的一組資料按某個增量 d(n/2,n 為排序數的個數) 分成若干組(把相隔 d 的資料分為一組),並在各組內進行直接插入排序,然後再用一個較小的增量 (d/2) 對它進行分組,在每組中再進行插入排序,當增量減到 1 時,進行插入排序後,排序完成。
假設有一個數組:
int[] arr = { 49, 38, 65, 97, 76, 13, 27, 49, 55, 04 };
- 先取一個增量 d = n/2 = 5,把每相隔 5 的資料分為一組,如下:
第一組 ---> 49 -- 13
第二組 ---> 38 -- 27
第三組 ---> 65 -- 49
第四組 ---> 97 -- 55
第五組 ---> 76 -- 04
- 每一組進行插入排序,如下:
第一組 ---> 13 -- 49
第二組 ---> 27 -- 38
第三組 ---> 49 -- 65
第四組 ---> 55 -- 97
第五組 ---> 04 -- 76
- 第一次的結果為:
{ 13, 27, 49, 55, 04, 49, 38, 65, 97, 76 };
- 取第二個增量 d2 = d/2 = 3,把每相隔 3 的資料分為一組,如下:
第一組 ---> 13 -- 55 -- 38 -- 76
第二組 ---> 27 -- 04 -- 65
第三組 ---> 49 -- 49 -- 97
- 每一組進行插入排序,如下:
第一組 ---> 13 -- 38 -- 55 -- 76
第二組 ---> 04 -- 27 -- 65
第三組 ---> 49 -- 49 -- 97
- 第二次的結果為:
{ 13, 04, 49, 38, 27, 49, 55, 65, 97, 76 };
- 取第三個增量 d3 = d2/2 = 1,把每相隔 1 的資料分為一組,這時開始直接插入排序即可,結果如下:
{ 04, 13, 27, 38, 49, 49, 55, 65, 76, 97 };
增量 d 取值為奇數。
3. 演算法圖解附視訊
視訊 點此檢視。
4. 演算法程式碼
import java.util.Arrays;
public class ShellSort {
public static void main(String[] args) {
int[] arr = { 49, 38, 65, 97, 76, 13, 27, 49, 55, 04 };
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
for (int d = arr.length / 2; d > 2; d /= 2) {
for (int i = 0; i < d; i++) {
insertSort(arr, i, d);
}
}
insertSort(arr, 0, 1);
}
// 插入排序
public static void insertSort(int[] arr, int i, int d) {
for (int a = i + d; a < arr.length; a += d) { // a += d
for (int j = a; (j >= d) && (arr[j] < arr[j - d]); j -= d) {
int temp = arr[j];
arr[j] = arr[j - d];
arr[j - d] = temp;
}
}
}
}