《演算法(第四版)》排序-----插入排序
阿新 • • 發佈:2019-01-28
插入排序:
插入排序與選擇排序一樣,當前索引左邊的所有元素都是有序的,但和選擇排序不一樣的是它們的位置不是固定的,可能為了更小的元素騰出空間,它們向後移動,但是當索引達到陣列的右端時,陣列排序就完成了 使用插入排序為一列數字進行排序的過程
具體演算法描述如下:
- 從第一個元素開始,該元素可以認為已經被排序
- 取出下一個元素,在已經排序的元素序列中從後向前掃描
- 如果該元素(已排序)大於新元素,將該元素移到下一位置
- 重複步驟3,直到找到已排序的元素小於或者等於新元素的位置
- 將新元素插入到該位置後
- 重複步驟2~5
與選擇排序的不同,插入排序所需的時間取決於輸入元素的初始順序,對一個很大且其中元素已經有序(或接近有序)的陣列進行排序比隨機順序的陣列或逆序的陣列排序要快的多。
最壞的請款進行n^2/2次比較和N^2/2次交換,最好情況進行N-1次比較,0次交換
平均 n^2/4次比較和N^2/4次交換,所以插入排序的比較次數平均只有選擇排序比較次數的一半
具體實現如下:
測試程式如下public static <T> void insertSort(Comparable<T>[] a){ // 將a[] 升序排列 int N = a.length; for (int i = 1; i < N; i++) {//預設a[0]已經是有序的了,所以從a[1]開始檢查 //檢查新的元素是否比前面的元素小,只要小就交換,直到不小位置,由於前面的已經是有序的了,有一個不小,那前面的都不小 for(int j = i; j > 0 && less(a[j],a[j-1]);j--) exch(a,j,j-1);//只要碰到小的就交換 } }
和選擇排序不同的是,插入排序所需要的時間取決有輸入中元素的出示順序,例如,對一個很大且其中的元素已經有序(或接近有序)的陣列進行排序將會比對隨機順序的陣列或逆序陣列進行排序要快的多。public class InsertionSort { public static <T> void insertSort(Comparable<T>[] a){ // 將a[] 升序排列 int N = a.length; for (int i = 1; i < N; i++) { for(int j = i; j > 0 && less(a[j],a[j-1]);j--){ exch(a,j,j-1); } } } private static <T>boolean less(Comparable<T> v, Comparable<T> w){ return v.compareTo((T) w) < 0; } private static <T> void exch(Comparable<T>[] a, int i, int j){ Comparable<T> t = a[i]; a[i] = a[j]; a[j] = t; } private static <T> void show(Comparable<T>[] a){ //在單行中列印陣列 for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } } public static <T> boolean isSorted(Comparable<T>[] a){ //測試陣列元素是否有序 for (int i = 0; i < a.length; i++) { if(less(a[i], a[i-1])) return false; } return true; } public static void main(String[] args) throws FileNotFoundException { // TODO Auto-generated method stub // String[] a = {"S","O","R","T","E","X","A","M","P","L","E"}; Integer[] a = {-5,8,9,5,7,1,-68,1,5,33,100,563,526,16,21,68,-88}; for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); insertSort(a); assert isSorted(a); show(a); } }