java 实现 常见排序算法(二) 插入排序
大家好,我是烤鴨:????
? ?今天分享一下基礎排序算法之直接插入排序。
?
1.? ? ?直接插入排序:
原理:假設前面的數為有序數列,然后有序數列與無序數列的每個數比較,我們可以從右向左比較
思路:從第2個數開始,和1比較。這樣前2個有序。
? ? ? ? ? ?第3個和前2個比較,這樣前3個有序。(如果是最小的,則第3個元素處在第1個位置,后面的元素后移1。)
? ? ? ? ? ?第4個和前3個比較,同上。
? ? ? ? ? ?直到第 n 個元素 和 前 n-1 個比較。
代碼實現:
/*** 直接插入排序* directInsertSort** @param array 時間復雜度,O的n^2* 直接插入排序就是我們假設前面的數為有序數列,然后有序數列與無序數列的每個數比較,我們可以從右向左比較* 當 array[i]<=array[j]=*/public void directInsertSort(int[] array) {long nowTime = System.currentTimeMillis();int tem = 0;for (int i = 1; i < array.length; i++) {int j = i - 1;tem = array[i];for (; j >= 0 && array[j] > tem; j--) {array[j + 1] = array[j];//將大于array[i]的數整體后移一單位}array[j + 1] = tem;}System.out.println("直接插入排序,花費時間(s):" + ((System.currentTimeMillis() - nowTime) / 1000.0) + "s");}2.? ? ?折半插入排序(優化):
思路:
其實和直接插入排序是類似的,只是在遍歷元素的時候采用的是二分法,直插采用的是順序遍歷。
取 temp 作為當前元素,
begin從0開始,end到數組最后一個元素。
如果temp < 中間值,begin從中間值+1繼續,否則 end 變為 end - 1 繼續,
begin 到 i 整體后移。
如圖:(圖片來源 http://www.cnblogs.com/chengxiao/p/6103002.html)
代碼實現:
/*** 折半插入排序* @param source* halfInsertSort** @param source 時間復雜度,O的n^2* 折半插入排序算法是一種穩定的排序算法,比直接插入算法明顯減少了關鍵字之間比較的次數,* 因此速度比直接插入排序算法快,但記錄移動的次數沒有變,所以折半插入排序算法的時間復雜度仍然為O(n^2),* 與直接插入排序算法相同*/public static void halfInsertSort(int[] source) {long nowTime = System.currentTimeMillis();int size = source.length;for (int i = 1; i < size; i++) {// 拿出來int temp = source[i];int begin = 0; // 標記排好序的數組的頭部int end = i - 1; // 標記排好序數組的尾部// 只要頭部一直小于尾部,說明temp還在2個標記范圍內while (begin <= end) {// 取2個標記的中間數據的值int mid = (begin + end) / 2;// 比較,若比中間值大,則范圍縮小一半if (temp > source[mid]) {begin = mid + 1;// 否則,范圍也是縮小一半} else {end = mid - 1;}// 循環結束時,end<begin,即i應該插入到begin所在的索引}// 從begin到i,集體后移for (int j = i; j > begin; j--) {source[j] = source[j - 1];}// 插入isource[begin] = temp;}System.out.println("折半插入排序,花費時間(s):" + ((System.currentTimeMillis() - nowTime) / 1000.0) + "s");}3.? ? ?shell排序
思路:
Shell排序也是對直接插入排序的改進。它實質上是一種分組插入方法。
下面希爾排序的步長選擇都是從n/2開始,每次再減半,直到最后為1。
時間復雜度 : O(nlog2^n)
/*** 希爾排序* 針對直接插入排序的下效率問題,有人對次進行了改進與升級,這就是現在的希爾排序。* 希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。希爾排序是非穩定排序算法。* 首先確定分的組數。* 然后對組中元素進行插入排序。* 然后將length/2,重復1,2步,直到length=0為止。* @param arr*/public void shellSort(int [] arr){long nowTime = System.currentTimeMillis();int len=arr.length;//單獨把數組長度拿出來,提高效率while(len!=0){len=len/2;for(int i=0;i<len;i++){//分組for(int j=i+len;j<arr.length;j+=len){//元素從第二個開始int k=j-len;//k為有序序列最后一位的位數int temp=arr[j];//要插入的元素/*for(;k>=0&&temp<arr[k];k-=len){arr[k+len]=arr[k];}*/while(k>=0&&temp<arr[k]){//從后往前遍歷arr[k+len]=arr[k];k-=len;//向后移動len位}arr[k+len]=temp;}}}System.out.println("希爾排序,花費時間(s):" + ((System.currentTimeMillis() - nowTime) / 1000.0) + "s");}?
耗時對比:
10W 條隨機 數據 運行如圖:
可以看出希爾排序時間明顯(比直插排序和折半排序)縮短。折半排序和直插排序時間差不多。
50W 條隨機 數據 運行如圖:
可以看出希爾排序時間明顯(比直插排序和折半排序)縮短。折半排序和直插排序時間差不多。
100W 條隨機 數據 運行如圖:
可以看出希爾排序時間明顯(比直插排序和折半排序)縮短。折半排序比直插排序耗時更多。
總結:
直接插入排序寫法比較簡單,平均時間復雜度為:O(n^2)?。
折半插入排序,平均時間復雜度為:O(n^2)?。
希爾排序,平均時間復雜度為:O(nlog2^n)?。
各種排序方法比較:
?
更多排序算法:
冒泡排序? ?:??https://blog.csdn.net/Angry_Mills/article/details/81057900
總結
以上是生活随笔為你收集整理的java 实现 常见排序算法(二) 插入排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Axure RP for Mac中文汉化
- 下一篇: 解析阿里云V3版本的专有云网络架构原理,