1. 程式人生 > >Java 排序之插入排序、希爾排序

Java 排序之插入排序、希爾排序

今天學習了一下 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;
			}
		}
	}
}