只有比別人更早、更勤奮地努力,才能嚐到成功的滋味。 ------麥克馬斯特大學訓言 html
http://bbs.itheima.com/thread-23776-1-1.html?fstgj java
之前的學習網站,-全套java視頻教程,須要的本身看下,能夠去這個網站下載,下載視頻免費,不須要註冊和作什麼任務 算法
記得以前總結過插入排序,有興趣的能夠看看---插入排序。 數組
若是在最複雜的狀況下,所要排序的整個數列是逆序的,當第 i-1 趟須要將 第 i 個元素插入前面的 0~ i -1 個元素的序列當中的時候,它老是會從第 i -1 個元素開始,逐個比較每一個元素的大小,直到找到相應的位置。 緩存
這個算法中絲毫沒有考慮當要插入第 i 個元素時前面的 0~~ i -1 序列是有序的這個特色。今天要總結的這個算法就充分的利用了這一點。 dom
算法的基本過程: 學習
1)計算 0 ~ i-1 的中間點,用 i 索引處的元素與中間值進行比較,若是 i 索引處的元素大,說明要插入的這個元素應該在中間值和剛加入i索引之間,反之,就是在剛開始的位置 到中間值的位置,這樣很簡單的完成了折半; 網站
2)在相應的半個範圍裏面找插入的位置時,不斷的用(1)步驟縮小範圍,不停的折半,範圍依次縮小爲 1/2 1/4 1/8 .......快速的肯定出第 i 個元素要插在什麼地方; spa
3)肯定位置以後,將整個序列後移,並將元素插入到相應位置。 code
算法實現:
import java.util.*; public class BinaryInsertSort { private static int[] Sort(int[] arr) { int i, j; //保存中間插入的值 int insertNote = 0; //將待排序的數列保存起來 int[] array = arr; System.out.println("開始排序:"); for (i = 1; i < array.length; i++) { int low = 0; int high = i - 1; insertNote = array[i]; //不斷的折半 while (low <= high) { //找出中間值 int mid = (low + high) / 2; //若是大於中間值 if (array[i] > array[mid]) { //在大於中間值的那部分查找 low = mid+1; } else //在小於中間值的那部分查找 high = mid-1; } //將總體數組向後移 for ( j=i; j > low; j--) { array[j] = array[j - 1]; } //插入到指定的位置 array[low] = insertNote; System.out.println(Arrays.toString(array)); } System.out.println("排序以後:"); System.out.println(Arrays.toString(array)); return array; } public static void main(String[] args) { Random random = new Random(); int[] array = new int[10]; for (int i = 0; i < 10; i++) { array[i] = Math.abs(random.nextInt() % 100); } System.out.println("排序以前:"); System.out.println(Arrays.toString(array)); BinaryInsertSort.Sort(array); } }
輸出截圖:
算法分析:
1)時間複雜度:
折半插入排序比直接插入排序明顯減小了關鍵字之間的比較次數,可是移動次數是沒有改變。因此,折半插入排序和插入排序的時間複雜度相同都是O(N^2),在減小了比較次數方面它確實至關優秀,因此該算法仍然比直接插入排序好。
2)空間複雜度:
折半插入排序和插入排序同樣只須要一個多餘的緩存數據單元來放第 i 個元素,因此空間複雜度是O(1),由於排序前2個相等的數在序列的先後位置順序和排序後它們兩個的先後位置順序相同,因此它是一個穩定排序。