1. 程式人生 > >十大經典排序演算法之插入排序(Insertion Sort)

十大經典排序演算法之插入排序(Insertion Sort)

插入排序(Insertion-Sort)的演算法描述是一種簡單直觀的排序演算法。它的工作原理是通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,通常採用in-place排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。

通俗點理解就是:每步將一個待排序的記錄,按其順序碼大小插入到前面已經排序的字序列的合適位置(從後向前找到合適位置後),直到全部插入排序完為止

1.1 演算法描述

一般來說,插入排序都採用in-place在陣列上實現。具體演算法描述如下:

  • 從第一個元素開始,該元素可以認為已經被排序;
  • 取出下一個元素,在已經排序的元素序列中從後向前掃描;
  • 如果該元素(已排序)大於新元素,將該元素移到下一位置;
  • 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;
  • 將新元素插入到該位置後;
  • 重複步驟2~5。

1.2 動圖演示

1.3 例題分析

有一陣列 int[] arr={3,1,5,4,2};使用插入排序每一趟的結果如下:

---------------------------------------------------------------

第一趟排序: 原始資料:3 1 5 4 2

1比3小,則1和3換位置

排序結果:1 3 5 4 2

---------------------------------------------------------------

第二趟排序: 5比3大,不需要調整

排序結果:1 3 5 4 2

---------------------------------------------------------------

第三趟排序: 4比5小,則4和5 換位置,

此時4比3大,則不再繼續調整

排序結果:1 3 4 5 2

---------------------------------------------------------------

第四趟排序: 2比5小,2和5換位置,2又比4小,

2繼續和4換位置,2仍然比3小,繼續和3換位置,

最後2比1大,不再調整

排序結果:1 2 3 4 5

---------------------------------------------------------------

1.4 程式碼展示

//定義了一個抽象方法,裡面是列印演算法排序的通用方法
public abstract class SortBase {
	public abstract int[] sort(int[] a);
	public static void print(String prefix, int[] arrayForSort) {
		System.out.print(prefix + ":");
		System.out.print("[");
		for (int i = 0; i < arrayForSort.length; i++) {
			if (i == arrayForSort.length - 1) {
				System.out.print(arrayForSort[i]);
			} else {
				System.out.print(arrayForSort[i] + " ,");
			}
		}
		System.out.println("]");
	}

}
import java.util.Scanner;

public class insertionSort extends SortBase {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("請輸入元素個數:");
		int n = sc.nextInt();
		int arr[] = new int[n];
		System.out.println("請依次輸入元素:");
		for (int i = 0; i < arr.length; i++) {
			arr[i] = sc.nextInt();
		}
		insertionSort is = new insertionSort();
		is.sort(arr);

	}

	@Override
	public int[] sort(int[] array) {
		//列印排序前的初始結果
		print("排序前", array);
		if (array.length == 0) {
			return array;
		}
		// 從下標為1開始比較,直到陣列的末尾
		for (int i = 1; i < array.length; i++) {
			int j;
			// 將要比較的元素存放到臨時變數中
			int temp = array[i];
			// 與前一元素一次比較,如果前一元素比要插入的元素大,則互換位置
			for (j = i - 1; j >= 0 && array[j] > temp; j--) {
				array[j + 1] = array[j];
			}
			// 將比較後的元素插入
			array[j + 1] = temp;
			//列印每一次排序的結果
			print("第" + i + "趟排序", array);
		}
		//列印最終排序的結果
		print("排序後", array);
		return array;
	}

}

1.5 測試案例

1.6 小結

插入排序的時間複雜度 就是判斷比較次數有多少,而比較次數與 待排陣列的初始順序有關,當待排陣列有序時,沒有移動操作此時複雜度為O(N),當待排陣列是逆序時,比較次數達到最大--對於下標 i 處的元素,需要比較 i-1 次。總的比較次數:1+2+...+N-1 ,故時間複雜度為O(N^2)