1. 程式人生 > 實用技巧 >排序-插入排序

排序-插入排序

https://en.wikipedia.org/wiki/Insertion_sort

對於插入排序

  • 原理:從低位到高位執行遍歷操作,遍歷到的元素作為對比元素存在;對於對比操作,實際是通過高位到低位,將比較元素和[0,比較元素所在索引-1]區間的資料進行對比操作以及交換(移動)操作; 對於移動操作而言只移動被比較的元素,在比較迴圈結束後,將比較元素寫入到空槽中;而無需在比較過程中就持續交換比較元素
  • 插入排序也不需要額外的陣列記憶體空間,只需要在原陣列上進行操作,因此屬於原地操作演算法
  • 穩定性:對於插入排序在比較操作時實際是通過高位和低位對比操作,當存在相同元素對比操作時,對於排序前後相同元素的相對位置並不會發生變化,因此屬於穩定排序

java程式碼實現

public interface Sort<T extends Comparable<T>> {
    /**
     * 對陣列進行排序
     *
     * @param array
     * @param flag  true 代表的是正序;false代表的是逆序
     */
    void sort(T[] array, boolean flag);
}

public class InsertSort<T extends Comparable<T>> implements Sort<T> {

    
/** * 插入排序 * 例如: * 5 4 3 2 1 * j i * j 和 j+1 位進行比較 * 5 > 4 ,交換 5 和 4 的位置,且 j 指向的索引為 0,比較中止,i的位置往後移動一位, j 的位置 為 i-1 * 4 5 3 2 1 * j i * 5 > 3,交換 5 和 3 的位置,但j指向的索引不為0.因此,繼續比較,i的位置不變,j的位置往前移動一位 * 4 3 5 2 1 * j i * 4 > 3,交換 3 和 4 的位置,且j指向的索引為 0 ,比較中止,i的位置往後移動一位,j的位置為 i - 1 * .............. * *
@param array * @param flag true 代表的是正序;false代表的是逆序 */ @Override public void sort(T[] array, boolean flag) { if (array == null || array.length < 2) { return; } int length = array.length; for (int i = 1; i < length; i++) { // 對於compareValue一直等於 array[j+1] T compareValue = array[i]; int j = i - 1; for (; j >= 0; j--) { // flag && array[j].compareTo(compareValue) == 1 (array[j] > compareValue) 升序 // !flag && array[j].compareTo(compareValue) == -1 (array[j] < compareValue) 降序 if ((flag && array[j].compareTo(compareValue) == 1) || (!flag && array[j].compareTo(compareValue) == -1)) { array[j + 1] = array[j]; // array[j] = compareValue;// 該交換操作實際是沒有必要的 } else { break; } } // 可以在全部比較操作都執行結束後,在結束遊標的後一位將當前比較的元素塞入陣列中 array[j + 1] = compareValue; } } public static void main(String[] args) { Integer[] values = new Integer[]{5, 3, 2, 1}; Sort<Integer> integerInsertSort = new InsertSort<>(); integerInsertSort.sort(values, true); Stream.of(values).forEach(System.out::print); System.out.println(); integerInsertSort.sort(values, false); Stream.of(values).forEach(System.out::print); } }

對於插入排序操作由於是從高位到低位進行對比,因此對於第一個元素實際沒有可比較資料,因此遍歷的起點從第二個元素開始,所以對於第一層for 迴圈中 i = 1而不是 "i = 0";這裡i的另一個含義表示的是提供比較元素;將使用當前i指向的元素和[0,i-1]區間的元素進行對比操作;

對於比較操作,插入排序比較操作是從高位到低位進行順序對比的;因此對於第二層迴圈 "j = i-1 ; j >=0 ; j--"; 對於[0,j]中的元素全部都是有序的,因此當存在不符合條件的對比操作時,直接終止當前迴圈操作,並將比較元素(array[i])插入當前[0,j]空閒插槽位置(j+1);

JDK實現

"JDK 15"

java.util.Arrays#mergeSort(java.lang.Object[], java.lang.Object[], int, int, int)

// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low &&
((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
swap(dest, j, j-1);
return;
}

"未完待續-----剩餘使用python+Matplotlib 繪製視覺化動畫"

https://zhuanlan.zhihu.com/p/38157591