1. 程式人生 > >在路上---學習篇(一)Python 數據結構和算法 (4) --希爾排序、歸並排序

在路上---學習篇(一)Python 數據結構和算法 (4) --希爾排序、歸並排序

改進 randint 循環 打印 中一 隨機 關鍵詞 shel 條件

獨白

  希爾排序是經過優化的插入排序算法,之前所學的排序在空間上都是使用列表本身。而歸並排序是利用增加新的空間,來換取時間復雜度的減少。這倆者理念完全不一樣,註定造成的所消耗的時間不同以及空間上的不同。

  歸並排序涉及到遞歸的使用,需要理解其中精髓才能更好了解歸並排序,以及其他應用到遞歸的算法。理解其本質才能更好的應用。


希爾排序

希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。該方法因DL.Shell於1959年提出而得名。 希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

時間復雜度

  • 最優時間復雜度:根據步長序列的不同而不同
  • 最壞時間復雜度:O(n2)
  • 穩定想:不穩定

"""
希爾排序
最優時間復雜度: 根據步長序列不同而不同
最壞時間復雜度: O(n*n)
穩定性 : 不穩定
"""

import time
import random


def shell_sort(list):
    n = len(list)
    #初始步長
    gap = n // 2
    while gap > 0:
        # 按初始步長進行插入排序
        for j in range(gap, n):
            i = j
            
# 插入排序 while i >= gap and list[i-gap] > list[i]: list[i-gap], list[i] = list[i], list[i-gap] i -= gap # 得到新的步長 gap = gap // 2 def new_num(lis): """隨機生成50個數加入列表中""" for i in range(50): j = random.randint(0, 10000) lis.append(j)
if __name__ == __main__: first_time = time.time() # 空列表 lis = [54,26,93,17,77,31] # 隨機函數添加到列表中 # new_num(lis) print(lis) # 列表排序 shell_sort(lis) print(lis) # 結束時間 last_time = time.time() print("共用時%s" % (last_time - first_time))

歸並排序

歸並排序是采用分治法的一個非常典型的應用。歸並排序的思想就是先遞歸分解數組,再合並數組。

將數組分解最小之後,然後合並兩個有序數組,基本思路是比較兩個數組的最前面的數,誰小就先取誰,取了後相應的指針就往後移一位。然後再比較,直至一個數組為空,最後把另一個數組的剩余部分復制過來即可。

時間復雜度

  • 最優時間復雜度:O(nlogn)
  • 最壞時間復雜度:O(nlogn)
  • 穩定性:穩定
"""
歸並排序
最優時間復雜度:O(nlogn)
最壞時間復雜度:O(nlogn)
穩定性:穩定


與其他排序區別
利用一個新列表講算法排序後的元素儲存當中
空間換時間
"""

import time
import random


def merge_sort(list):
    """歸並排序"""
    n = len(list)
    if n <= 1:
        return list
    # 最大整除
    mid = n // 2
    # left 利用遞歸  截取的列表形成的有序列表
    left_list = merge_sort(list[:mid])
    # right 利用遞歸  截取的列表形成的有序列表
    right_list =merge_sort(list[mid:])
    # 創建 左右遊標記錄列表值的索引
    left_pointer, right_pointer = 0,0
    # 創建新空列表
    result = []
    # 循環 比較數值大小
    # 退出循環條件 當左右遊標其中一個等於所在列表的長度時
    while left_pointer < len(left_list) and right_pointer < len(right_list):
        # 判斷 左值和右值大小
        if left_list[left_pointer] <= right_list[right_pointer]:
            result.append(left_list[left_pointer])
            # 每判斷一次 遊標加一
            left_pointer += 1
        else:
            result.append(right_list[right_pointer])
            right_pointer += 1
    # 將最後一個數值加入新列表中
    result += left_list[left_pointer:]
    result += right_list[right_pointer:]
    # 返回值
    return result


def new_num(lis):
    """隨機生成50個數加入列表中"""
    for i in range(50):
        j = random.randint(0, 100)
        lis.append(j)

if __name__ == __main__:
    first_time = time.time()
    # 空列表
    lis = []

    # 隨機函數添加到列表中
    new_num(lis)
    print(lis)

    # 列表排序
    # 因為歸並排序最後是返回一個新列表,所以打印輸出為新列表
    alist = merge_sort(lis)
    print(alist)

    # 結束時間
    last_time = time.time()

    print("共用時%s" % (last_time - first_time))

在路上---學習篇(一)Python 數據結構和算法 (4) --希爾排序、歸並排序