排序演算法之折半插入排序
1 、介紹。
將直接插入排序中尋找A[i] 的插入位置的方法改為採用折半比較,即可得到折半插入排序演算法。在處理 A[i] 時, A[0] …… A[i-1] 已經按關鍵碼值排好序。所謂折半比較,就是在插入 A[i] 時,取 A[i-1/2] 的關鍵碼值與 A[i] 的關鍵碼值進行比較,如果 A[i] 的關鍵碼值小於 A[i-1/2] 的關鍵碼值,則說明 A[i] 只能插入 A[0] 到 A[i-1/2] 之間,故可以在外匯返傭http://www.kaifx.cn/ A[0] 到 A[i-1/2-1] 之間繼續使用折半比較;否則只能插入 A[i-1/2] 到 A[i-1] 之間,故可以在 A[i-1/2+1] 到 A[i-1] 之間繼續使用折半比較。如此擔負,直到最後能夠確定插入的位置為止。一般在 A[k] 和 A[r] 之間採用折半,其中間結點為 A[k+r/2] ,經過一次比較即可排除一半記錄,把可能插入的區間減小了一半,故稱為折半。執行折半插入排序的前提是檔案記錄必須按順序儲存。
折半插入排序是穩定排序,不需要額外記憶體,空間複雜度O(1) 。時間複雜度,最佳情況: O(n^2) 最差情況: O(n^2) 平均情況: O(n^2) 。
2 、步驟。
跟直接插入排序的步驟相似,只不過查詢插入點的方法不一樣。直接插入排序是從有序區的最後一個數依次向前找,而折半插入排序是通過折半的方式進行查詢。
(1) 計算 0 ~ i-1 的中間點,用 i 索引處的元素與中間值進行比較,如果 i 索引處的元素大,說明要插入的這個元素應該在中間值和剛加入 i 索引之間,反之,就是在剛開始的位置 到中間值的位置,這樣很簡單的完成了折半;
(2) 在相應的半個範圍裡面找插入的位置時,不斷的用( 1 )步驟縮小範圍,不停的折半,範圍依次縮小為 1/2 1/4 1/8 ....... 快速的確定出第 i 個元素要插在什麼地方;
(3) 確定位置之後,將整個序列後移,並將元素插入到相應位置。
3 、程式碼。
public static void main(String[] args) {
System.out.println("------ 開始 ------");
// 生成生成兩份隨機陣列,其中用系統自帶的方法進行排序,到時候進行驗證。
final int number = 100000;
int[] sortArray = new int[number];
int[] sortArrayCopy = new int[number];
for (int i = 0; i < sortArray.length; i++) {
sortArray[i] = (int) (Math.random() * number);
}
System.arraycopy(sortArray, 0, sortArrayCopy, 0, number);// 陣列複製
Arrays.sort(sortArrayCopy);
// 開始排序
long startTime = System.currentTimeMillis();
halveInsertSort(sortArray);// 折半插入排序
System.out.println(" 花費時間: " + (System.currentTimeMillis() - startTime));
// 跟系統排序之後陣列進行比較,檢視是否排序成功。
if (Arrays.equals(sortArray, sortArrayCopy)) {
System.out.println(" 排序成功 ");
} else {
System.out.println(" 排序失敗 ");
}
System.out.println("------ 結束 ------");
}
// 折半插入排序 最佳情況: T(n) = O(n) 最壞情況: T(n) = O(n2) 平均情況: T(n) = O(n2)
private static void halveInsertSort(int[] array) {
int flag;
int low, middle, high;
for (int i = 1; i < array.length; i++) {//n-1 輪
flag = array[i];
low = 0;
high = i - 1;
while (low <= high) {// 最後的情況就是 low==high==middle 的判斷
middle = (low + high) / 2;
if (array[i] > array[middle]) {
low = middle + 1;
} else {
high = middle - 1;
}
}
for (int j = i; j > high + 1; j--) {
array[j] = array[j - 1];
}
array[high + 1] = flag;
}
}
public class InsertSort {
/* 使用折半插入法進行排序 */
public static void main(String[] args) {
int array[]=new int[]{9,8,7,6,5,4,3,2,1}; // 把待排序的數存放在陣列中
int i,j,temp;
int low,high,mid;
for(i=1;i<array.length;i++){// 需要進行 n-1 趟插入排序
temp=array[i];
low=0;
high=i-1;
while(low<=high){ // 折半查詢插入位置
mid=(low+high)/2;
if(array[mid]>temp){
high=mid-1;
}else{
low=mid+1;
}
}
for(j=i-1;j>=low;j--){ // 後移
array[j+1]=array[j];
}
array[low]=temp; // 插入
}
for(i=0;i<array.length;i++){
System.out.print(array[i]+" ");
}
}
}
型別定義標頭檔案
#define MAXSIZE 20 /* 一個用作示例的小順序表的最大長度 */
typedef int InfoType; /* 定義其它資料項的型別 */
typedef int KeyType; /* 定義關鍵字型別為整型 */
typedef struct
{
KeyType key; /* 關鍵字項 */
InfoType otherinfo; /* 其它資料項,具體型別在主程中定義 */
}RedType; /* 記錄型別 */
typedef struct
{
RedType r[MAXSIZE+1]; /* r[0] 閒置或用作哨兵單元 */
int length; /* 順序表長度 */
}SqList; /* 順序表型別 */
函式檔案
void BinInsertSort(SqList *L)
/* 折半插入排序 */
{
int i,j,mid,low,high;
DataType t;
for(i=1;i<L->length;i++) /* 前 i 個元素已經有序,從第 i+1 個元素開始與前 i 個的有序的關鍵字比較 */
{
t=L->data[i+1]; /* 取出第 i+1 個元素,即待排序的元素 */
low=1,high=i;
while(low<=high) /* 利用折半查詢思想尋找當前元素的合適位置 */
{
mid=(low+high)/2;
if(L->data[mid].key>t.key)
high=mid-1;
else
low=mid+1;
}
for(j=i;j>=low;j--) /* 移動元素,空出要插入的位置 */
L->data[j+1]=L->data[j];
L->data[low]=t; /* 將當前元素插入合適的位置 */
}
}
主程式
#define LT(a,b) ((a)<(b))
#define N 8
void print(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
printf("\n");
}
void main()
{
RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};
SqList l;
int i;
for(i=0;i<N;i++) /* 給 l1.r 賦值 */
l1.r[i+1]=d[i];
l.length=N;
printf(" 排序前 :\n");
print(l);
BInsertSort(&l);
printf(" 折半插入排序後 :\n");
print(l);
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69946279/viewspace-2660762/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 排序演算法__折半插入排序排序演算法
- 經典演算法之折半插入排序演算法排序
- [java]插入排序及折半插入排序Java排序
- 【筆記】折半插入排序筆記排序
- 三種插入排序 直接插入排序,折半插入排序,希爾排序排序
- 【排序】插入類排序—(折半)插入排序、希爾排序排序
- PHP 排序演算法之插入排序PHP排序演算法
- C語言例題19:折半插入排序C語言排序
- 排序演算法入門之「插入排序」排序演算法
- Java常見排序演算法之插入排序Java排序演算法
- 排序演算法之「插入排序(Insertion Sort)」排序演算法
- 排序之插入排序排序
- PHP 演算法02之插入排序PHP演算法排序
- 小白懂演算法之插入排序演算法排序
- 死磕演算法之插入排序演算法排序
- 畫江湖之演算法篇【排序演算法】插入排序演算法排序
- 畫江湖之演算法篇 [排序演算法] 插入排序演算法排序
- 排序演算法:插入折半排序 PHP 版排序演算法PHP
- 排序演算法——插入排序排序演算法
- 排序演算法之——二分插入排序演算法排序演算法
- 【演算法】插入排序演算法排序
- 排序演算法 - 快速插入排序和希爾排序排序演算法
- 排序演算法:插入排序演算法 PHP 版排序演算法PHP
- 常用演算法-插入排序演算法排序
- 排序演算法__直接插入排序排序演算法
- 排序演算法:直接插入排序排序演算法
- 排序演算法——直接插入排序排序演算法
- 排序演算法-直接插入排序排序演算法
- Python演算法之---冒泡,選擇,插入排序演算法Python演算法排序
- 04資料結構排序演算法之直接插入排序資料結構排序演算法
- 實時插入排序演算法排序演算法
- 演算法學習之直接插入排序(java)演算法排序Java
- 排序演算法(氣泡排序,選擇排序,插入排序,希爾排序)排序演算法
- 排序演算法(3)插入排序(Insertion Sort)排序演算法
- 排序演算法:二分插入排序排序演算法
- 排序演算法——二分插入排序排序演算法
- #排序演算法#【2】直接插入排序、希爾排序排序演算法
- 對c語言系統庫函式、堆排序、希爾排序、折半插入排序、快速排序消耗時間的比較C語言函式排序