插入排序 簡單插入排序 二分插入排序

2021-09-30 12:31:26 字數 4185 閱讀 9649

1)假設我們手裡的數字是一堆亂序撲克牌,我們想把它整理成從小到大的排序,會怎麼辦呢,我們會從左往右挨個將牌抽出來插到它合適的位置,這樣一輪之後,就變成從小到大的順序了。

2)程式上怎麼實現,從第二位開始,逐個將後乙個數和它之前所有的資料進行比較,尋找這個數最合適的插入位置,將其插入空隙,後面的值依次會往後移動一位,迴圈一遍之後,可實現排序。

如果陣列的前面部分已經有序,找到合適的位置這個操作,可以使用二分查詢法來找,這樣單詞查詢的效率由o(n)變為o(logn),其它操作不變

1)四個引數,陣列arr,目標值value,起點位置startindex,終點位置endindex

2)一開始startindex和endindex分別為0和i-1(寫排序演算法時,盡量設定的值包含邊界),因為當前元素就在i的位置,應該在0~i-1個元素之間找。

最終二分查詢的返回值應該是0~i之間,因為多了乙個當前元素i,所以返回值也是0~i

3)找到一半的位置(startindex+endindex)/2,前半部分認為是[0 ~ halfindex],後半部分認為是[halfindex + 1 ~ endindex]

4)如果value大於等於halfindex位置的值,則往後找,否則往前找(保證穩定性)

5)直到startindex == endindex,這個時候遞迴應該退出

這個時候判斷,如果value仍然大於等於halfindex的值,那麼返回halfindex + 1

如果vallue小於halfindex的值,那麼value就應該放在halfindex的位置,返回halfindex

兩重迴圈,所以時間複雜度是o(n^2)

細分一下:(查詢 (o(n)或者o(logn)+ 交換目標位置和當前位置元素o(1) + 整體後移(o(n)))* n次,所以是o(n^2),二分只能一定程度上節約查詢的效率,大頭其實是交換

所以我們假設只按照交換來計算,最壞的情況是倒序,1+2+3+...+(n-1) = n(n-1) / 2 = o(n^2)

最好的情況順序,o(n)

**的實現可以保證穩定性,是穩定的演算法

網上有個什麼「監視哨」,就是將乙個陣列自身的元素作為邊界,將比較的判斷和超出邊界合併(一般都是超出邊界作為監視哨中的可合併條件),使用乙個條件來判斷,這樣減少乙個判斷,這個判斷在資料量特別大的時候效率提公升會很明顯。

比如每次從i判斷到j>=0,這個j>=0可以和下面的arr[i] >= arr[j]結合起來,也就是把條件放到乙個可達到的位置,這樣就不用每次判斷陣列是否越界了。

比如要查詢某個元素,直到找到最後乙個,我們會判斷是否越界,其實可以把這個值放到第0位,如果返回0,認為沒找到

這個在插入演算法中好像不好用,如果使用二分查詢法,這個就沒有意義了,並且這玩意要提前複製陣列吧。

indexsort1為普通的,每次都叫喚,indexsort2為公升級後的,捏著當前的值,直到找到合適的位置放下

public static voidmain(string args);

system.

out

.println(arrays.

tostring

(insertsort1

(arr)));

arr =

new int;

system.

out

.println(arrays.

tostring

(insertsort2

(arr)));

arr =

new int;

system.

out

.println(arrays.

tostring

(insertsort3

(arr)));

}/**

* 從第二個數(index=1)開始,逐個向前找到合適的位置放入

* 這個存在的問題是,交換的次數過多,並且可能並不是有效交換

*@param

arr

*@return

*/private static intinsertsort1(

intarr)

else}}

returnarr;

}private static intinsertsort2(

intarr)

// 記錄下標

idx = j;

}// 將到i為止的資料,全部往後移一位

for(

intj = i; j > idx; j--)

// 將v放下

arr[idx] = v;

}returnarr;

}/**

* 既然前面有序,可以使用二分查詢法,查詢到應該放入的位置

*@param

arr

*@return

*/private static intinsertsort3(

intarr)

for(

intj = i;j > targetindex;j--)

arr[targetindex] = v;

}returnarr;

}/**

* 從一般到特殊,推導二分查詢的規則

* 1、找到一半的位置,前面為0-halfindex,後面halfindex + 1 到 endindex

* 2、和中間位置比較,如果大於等於,則向後判斷,如果小於則向前判斷(大於等於,保證穩定性)

* 3、直到startindex == endindex,這一步肯定要return,遞迴結束

* 4、判斷如果當前位置大於value,那就是這個位置(有的演算法是halfindex-1),就不明白了,假設是0的位置,-1不就成負值了,不直觀,巨集觀上講,找到的位置介於0-i+1之間(i+1是因為一串i的陣列現在多了乙個元素,當然變成了n+1長度的陣列)

* 5、如果是小於等於value,說明推到了最後,返回halfindex+1

*@param

arr

*@param

value

*@param

startindex

*@param

endindex

*@return

*/private static intbinarysearch(

intarr,

intvalue,

intstartindex,

intendindex)

else

}if(value >= arr[halfindex])

else

}

二分插入排序

基本思想 1.取arr 1 為關鍵字key,將key插入前面已拍好的序列中。2.取arr 2 為關鍵字key,將key插入前面已拍好的序列中。3.取arr n 1 為關鍵字key,將key插入前面已拍好的序列中。include include define n 10 void binsertsort...

二分插入排序

include 二分插入法排序 二分排序的時間複雜度是o n logn 空間複雜度o 1 是穩定排序 void binary insert sort int a,int len else 如果當前元素比中間元素大,當前元素要插入到中間元素的右側 for j i 1 j high j 元素後移 a h...

二分插入排序

一 折半插入排序 二分插入排序 二 演算法原理 演算法的基本過程 1 計算 0 i 1 的中間點,用 i 索引處的元素與中間值進行比較,如果 i 索引處的元素大,說明要插入的這個元素應該在中間值和剛加入i索引之間,反之,就是在剛開始的位置 到中間值的位置,這樣很簡單的完成了折半 2 在相應的半個範圍...