直接插入排序(python實現)


這篇博文用來介紹直接插入排序

 

直接插入排序基本思想:

每次將一個待排序的記錄插入到已經排好序的數據區中,直到全部插入完為止

 

直接插入排序算法思路:

在直接插入排序中,數據元素分為了有序區和無序區兩個部分,在這里我們將列表左邊部分作為有序區,列表右邊部分作為無序區,有序區和無序區的大小是隨着排序的進行而變化的。

如最開始列表是無序的,所以有序區長度為1,無序區長度為列表長度-1,排序結束后,列表變為有序,則有序區長度為列表長度,無序區長度為0.

具體步驟為:

排序過程中每次從無序區中取出第一個元素,將它插入到有序區中的適當位置(即該元素放在此位置,有序區仍然有序),使之成為新的有序區,重復n-1次可完成排序過程。

 

 

假設需要將列表從小到大排序

 想要將從無序區中取出的第一個元素temp插入到有序區中的適當位置,需要有一個循環遍歷的過程,即從該元素位置處依次向前比較,會有兩種情況:

  1,前面的元素waitsortlist[j-1]大於temp,則temp需要繼續向前比較,同時大於temp的元素需要后移一位

  2,前面的元素waitsortlist[j-1]小於等於temp,則temp不需要繼續比較了,因為temp大於有序區中最大的元素,有序區伸展一位,包含temp

另外還需要考慮 j 的邊界問題,因為會用到 j-1,所以 j 需要>=1防止越界,對於無序區某一個元素temp的直接插入代碼如下:

        temp=waitsortlist[j]
        while j>=1:
            if temp<waitsortlist[j-1]:
                waitsortlist[j]=waitsortlist[j-1]
                j=j-1
            else:
                break
        waitsortlist[j]=temp

 外層是一個列表的遍歷,加上上面的代碼為:

 

    i=0
    j=i+1
    while j<len(waitsortlist):
        temp=waitsortlist[j]
        while j>=1:
            if temp<waitsortlist[j-1]:
                waitsortlist[j]=waitsortlist[j-1]
                j=j-1
            else:
                break
        waitsortlist[j]=temp
        i=i+1
        j=i+1

  可以看出,列表的第一個元素必為有序區,遍歷的過程中不斷擴大有序區的范圍,對於列表某一個元素來說,就是將其插入在有序區中適當的位置,外層循環遍歷結束后,有序區也擴充為列表長度,即排序結束。

該算法的時間復雜度為O(n^2),因為有兩層循環,時間開銷比較大,空間復雜度為O(1),只是用了常數階的空間來存儲變量,用以直接插入排序

 

全部代碼為(實際上看了前面的相信你已經能寫出來了:D

'''
    直接插入排序
'''
def DirectInsertionSort(waitsortlist):
    i=0
    j=i+1
    while j<len(waitsortlist):
        temp=waitsortlist[j]
        while j>=1:
            if temp<waitsortlist[j-1]:
                waitsortlist[j]=waitsortlist[j-1]
                j=j-1
            else:
                break
        waitsortlist[j]=temp
        i=i+1
        j=i+1
    return waitsortlist


if __name__=='__main__':
    waitsortlist=[9,8,7,6,5,4,3,2,1,0]
    print(DirectInsertionSort(waitsortlist))

  運行結果為:

 

直接插入排序 (帶監視哨):

哨兵的概念:一切為簡化邊界條件而引入的附加結點(元素)均可稱為哨兵。

在上面的代碼我們可以看到有這一段:

while j>=1:

  內循環每一次比較前都需要判斷 j 是否越界,有沒有不需要判斷的辦法呢?當然有,這就是哨兵的作用

將上面的代碼改為:

def DirectInsertionSortEye(waitsortlist):
    i=1
    j=i+1
    while j<len(waitsortlist):
        temp=waitsortlist[j]
        waitsortlist[0]=temp
        while temp<waitsortlist[j-1]:
            waitsortlist[j]=waitsortlist[j-1]
            j=j-1
        waitsortlist[j]=temp
        i=i+1
        j=i+1
    return waitsortlist

if __name__=='__main__':
    waitsortlist=[0,9,8,7,6,5,4,3,2,1,0]
    print(DirectInsertionSortEye(waitsortlist))

  輸出的結果為:

 

 我們將waitsortlist[0]設置為哨兵,傳入列表的時候,該位置也不能夠放置有效元素,用列表一個元素的空間判斷越界與否的比較時間。可以看出,一次循環少判斷一次,n次循環少判斷n次,當數據量較大時,很明顯是優於不帶監視哨的直接插入排序。

帶監視哨的直接插入排序思想也很簡單,在原有基礎上稍加修改即可,這里不再贅述。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM