1. 程式人生 > >插入排序與迴圈不變式

插入排序與迴圈不變式

插入排序

《演算法導論》第一部分中並沒有詳細講解某一種演算法,而是以講解演算法這個概念,而插入排序是講解演算法基礎的例子。

輸入: n 個數的一個序列 <a1, a2, ..., an>。
輸出: 輸入序列的一個排列 <a1', a2', ..., an'>

因為演算法很簡單,就直接上程式碼:

A = [2, 5, 1, 3, 7, 6]

def instertion_sort(nums):
    for i in range(1, len(nums)):
        key = nums[i]
        j = i - 1
        while j >= 0 and nums[j] > key: # compare nums[j] and key
            nums[j + 1] = nums[j]
            j -= 1
        nums[j + 1] = key # set nums[j + 1] is key
    return nums


if __name__ == '__main__':
    print(instertion_sort(A))

下午看完了第二章第二節之後,晚上嘗試完全憑記憶敲這段程式碼,結果還是出了兩個問題,就是我打註釋的兩個地方。

第一個是 while 的判斷條件,j 的臨界條件是不小於 0,可能因為導論的陣列是從 1 開始的,進過我已經意識到了,在寫 range 的時候就意識到了,但是我手寫的時候依然寫的是 j > 0,可能只是下意識的擔心越界。

第二個地方就是 nums[j + 1] = key,我一開始的時候寫的是,nums[i] = key,這個應該是純粹腦殘了,因為 while 以 key 為基準,對前 i 個數字排排坐,而 key 最後落座在哪裡,是通過 while 迴圈跑出來的,也就是說是和 j 的值相關。

迴圈不變式

迴圈不變式是驗證迴圈正確性的一種方法,關注迴圈體中的主要的屬性(比如在插入排序中 nums[0...i-1] 這段數字是保持遞增的屬性),如果這種屬效能在開始迴圈時迴圈中結束迴圈後,都一直保持,那麼我們就認為這個迴圈是正常工作的。

在演算法導論中嘗試使用數學歸納法來驗證這個迴圈:

初始化: 迴圈得第一次迭代之前,它為真
保持: 如果迴圈的某次迭代之前它為真,那麼下次迭代之前它仍為真
終止: 在迴圈終止時,不變式為我們提供一個有用的性質,該性質有助於證明演算法是正確的。

因為這三個狀態(開始,進行,結束),nums[0...i-1] 始終保持了遞增這一個屬性,因此驗證了插入排序這個演算法的正確性。


歡迎到微信裡去當吃瓜群眾