折半插入排序


算法簡介

折半插入排序(binary insertion sort)是對插入排序算法的一種改進,由於排序算法過程中,就是不斷的依次將元素插入前面已排好序的序列中。由於前半部分為已排好序的數列,這樣我們不用按順序依次尋找插入點,可以采用折半查找的方法來加快尋找插入點的速度。

算法動態演示:

 

算法思想 

折半插入排序利用二分法的思想,在一個有序的序列中,找到新元素在該序列中的位置,然后插入。如圖1所示,共有n個元素,前i個元素已經是有序序列,現在要將第i個元素插入其中。折半插入排序需要做兩步工作:找到待插入元素的位置、插入。

 

                                                     圖1 插入排序示意圖

 首先要定義兩個指針(不是語法里面的指針,是下標的意思)low和high用於尋找a[i]的插入位置,low指向a[0],high指向a[i-1],中點mid=(low+high)/2.

                                                  圖2 “折半”示意圖

如圖2所示二分法的思想是,比較a[i]與a[mid]的大小,若a[i]>a[mid],說明a[i]的位置應該在mid~high之間,將區間[low,high]縮短為[mid+1,high],令指針low=mid+1;若a[i]<=a[mid],說明a[i]的位置應該在low~mid之間,將區間壓縮為[low,mid-1],令指針high=mid-1。每次折半之后,a[i]的位置應該在[low,high]之間。

如此循環,low與high漸漸靠近,直到low>high跳出循環,a[i]的位置找到,low即為a[i]應該放置的位置。

找到a[i]的位置之后進行插入,先將a[low]~a[i-1]這些元素向后平移一個元素的位置,然后將a[i]放到low位置。

 

算法分析

一個細節:為什么內層的循環while(low<=high){...}結束之后以low作為a[i]應該放置的位置?

第一種情況

a[mid] < a[i] <=  a[high]:

第N-2步時,mid=(low+high)/2,如果a[i]>a[mid],low=mid+1,這樣就到了第N-1步,low與high重合,high=mid-1,這樣就到了第N步,high<low,退出循環,此時位置high就是第N-2步的位置mid,所以此時,a[high]<a[i]<=a[low],所以low就是a[i]應該放置的位置。

 

第二種情況

a[low] <=  a[i] <  a[mid]:

 第N-2步,mid=(low+high) / 2,如果a[i] <= a[mid],high = mid-1,這樣就到了第N-1步,low與high重合,mid=(low+high)/2=low=high,由於a[i]>a[low]=a[mid],所以low=mid+1,這樣就到了第N步,high<low,退出循環,此時位置low就是第N-2步的位置mid,那么此時,a[high]<a[i]<=a[low],所以low就是a[i]應該放置的位置。

 

 

典型的例子是一個父進程fork子進程之后,父進程立即退出,這樣子進程所在的進程組將變為孤兒進程組。這樣的孤兒進程組中的每個停止(Stopped)狀態的每個進程都將收到掛斷信號(SIGHUP),然后又立即收到繼續信號(SIGCONT)。所以fork子進程之后,退出父進程,如果子進程還需要繼續運行,則需要處理掛斷信號,否則進程對掛斷信號的默認處理將是退出。

此時的孤兒進程組並沒有變為后台進程,一些博客將后台進程說成是孤兒進程組的一個特點,筆者認為是不正確的,在他們的示例中,孤兒進程組變為后台進程的原因是:父進程退出后,子進程在運行時向自身發送了SIGTSTP信號,這就像在終端按下終端掛起鍵(ctrl+z)一樣,暫時斷開了進程與控制終端的連接,自然變成了后台進程。

所以這是將進程轉到后台運行的一個手段,但並不能創建守護進程,后面會將怎么創建守護進程。

參考資料

1. 折半插入排序


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: