【排序】折半插入排序
目錄
折半插入排序原理
折半插入排序圖文說(shuō)明
代碼實(shí)現(xiàn)
C實(shí)現(xiàn)
?JAVA實(shí)現(xiàn)
?復(fù)雜度分析和穩(wěn)定性
復(fù)雜度
穩(wěn)定性
總結(jié)
折半插入排序原理
折半插入排序是對(duì)直接插入排序的一種改良方式,在直接插入排序中,每次向已排序序列中插入元素時(shí),都要去尋找插入元素的合適位置,但是這個(gè)過(guò)程是從已排序序列的最后開(kāi)始逐一去比較大小的,這其實(shí)很是浪費(fèi),因?yàn)槊勘容^一次緊接著就是元素的移動(dòng)。折半排序就是通過(guò)折半的方式去找到合適的位置,然后一次性進(jìn)行移動(dòng),為插入的元素騰出位置。什么是折半的方式去找合適的位置呢,那就是折半查找了,因?yàn)樵僖雅判虻男蛄兄?#xff0c;序列元素都是按照順序排列的,既然這樣,完全不需要逐一去比較大小,而是去比較已排序序列的中位數(shù),這個(gè)中間的位置將一排序列分為左右兩部分,通過(guò)一次比較后,就縮小了比較的范圍,重復(fù)這樣的操作,需要插入的元素就找到了合適的位置了。
折半插入排序圖文說(shuō)明
注:藍(lán)色代表已排序序列,白色代表未排序序列,紅色箭頭指向未排序序列的第一個(gè)元素位置。
?
如圖所示,現(xiàn)在有一個(gè)待排序序列[8 5 4 2 3],首先默認(rèn)初始狀態(tài)下,位置0的數(shù)字8作為已排序序列[8],位置1--位置4的[5 4 2 3 1]?為待排序序列,之后就逐一從[5 4 2 3 1]中取出數(shù)字向前進(jìn)行比較,插入到已排序序列的合適位置。尋找過(guò)程中將藍(lán)色的已排序區(qū)域不斷進(jìn)行折半。
初始狀態(tài)下,已排序區(qū)只有一個(gè)數(shù)據(jù)元素8,low位置和high位置都指向了該位置,mid為中間位置,此時(shí)很顯然也是0位(0+0)/ 2。此時(shí)temp < mid,將high指向mid的前一位,這里也就是-1,這個(gè)時(shí)候high=-1,low=1,很顯然high<low,每當(dāng)這個(gè)時(shí)候,就到了移動(dòng)元素的時(shí)候了,將(high+1)到(i-1)的元素都向后移一位,再把(high+1)位置上插入要插入的元素。
之后的操作也是這樣類(lèi)似的,詳細(xì)過(guò)程如下圖。
?
代碼實(shí)現(xiàn)
C實(shí)現(xiàn)
代碼:
#include <stdio.h>void insertSort(int array[], int n){int temp;for(int i = 1; i < n; i++){int low = 0;int hight = i-1;temp = array[i];while(hight>=low){int mid = ( low + hight ) / 2;if (array[mid] > temp){hight = mid - 1;}else{low = mid + 1;}}for (int j = i-1; j > hight; j--) {array[j+1] = array[j];}array[hight+1] = temp;} }void main(){int i;int a[8] = { 8, 5, 4, 3, 2, 1, 6, 7 };printf("before:{");for(i = 0; i < 8; i++){printf("%d ",a[i]);}printf("}\n");insertSort(a,8);printf("after:{");for(i = 0; i < 8; i++){printf("%d ",a[i]);}printf("}\n");}測(cè)試結(jié)果:?
?JAVA實(shí)現(xiàn)
代碼:
/*** Created by GFC on 2018/8/29.*/ public class HalfSearchSort {public void sort(int[] array){int temp;for(int i = 1; i < array.length; i++){int low = 0;int hight = i-1;temp = array[i];while(hight>=low){int mid = ( low + hight ) / 2;if (array[mid] > temp){hight = mid - 1;}else{low = mid + 1;}}for (int j = i-1; j > hight; j--) {array[j+1] = array[j];}array[hight+1] = temp;}}public static void main(String[] args) {HalfSearchSort sort = new HalfSearchSort();int a[] = {8, 5, 4, 3, 2, 1, 6, 7};System.out.println("Before: " + Arrays.toString(a));//System.out.println(5/2);sort.sort(a);System.out.println("After: " + Arrays.toString(a));} }?測(cè)試結(jié)果:
?復(fù)雜度分析和穩(wěn)定性
復(fù)雜度
和直接插入排序相比較,折半插入排序僅僅是減少了比較的次數(shù),而移動(dòng)總次數(shù)并沒(méi)有發(fā)生改變。這個(gè)比較次數(shù)大概是,移動(dòng)次數(shù)沒(méi)有改變,所以其復(fù)雜度和直接插入排序是一樣的。
穩(wěn)定性
根據(jù)代碼分析可以知道,當(dāng)待插入數(shù)與mid位置的值相等時(shí),接下來(lái)相當(dāng)于進(jìn)入了有序序列的右半?yún)^(qū),mid+1到high,之后經(jīng)過(guò)多次折半查找,該元素所找到的合適位置就是前一個(gè)與之相等元素的后一位,所以說(shuō)兩者相對(duì)位置沒(méi)有發(fā)生變化,這般插入排序是穩(wěn)定的。
總結(jié)
折半插入排序其實(shí)是在直接插入排序的基礎(chǔ)上,結(jié)合了二分查找法的思想,順序的二分查找替代了直接插入排序中遍歷查找的過(guò)程,從而更快的能夠確定待插入元素的位置,但是由于移動(dòng)次數(shù)并沒(méi)有發(fā)生改變,所以?xún)烧叩臅r(shí)間復(fù)雜度相同。折半插入排序是穩(wěn)定的,其時(shí)間復(fù)雜度為。
?
總結(jié)
以上是生活随笔為你收集整理的【排序】折半插入排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 安装 Cartographer问题记录汇
- 下一篇: VS2017编译文件遇到fatal er