天天看點

Python資料結構與算法(六)--歸并排序、排序總結、二分查找 歸并排序排序比較 搜尋

歸并排序

  • 思想

簡單地将原始序列劃分成兩個子序列,分别對每個子序列遞歸排序,最後将排好序的子序列合并為一個有序序列

先拆成一個一個的,然後兩個合并一起,并排好序

兩個兩個的合并成四個的時候,需要左邊一個指針left指向左邊第一個元素,右邊一個指針right指向右邊第一個元素,兩個元素比較,誰小放到左邊,然後挪一下指針

  • 性質

穩定

時間複雜度:

O(nlogn)

(最優、最壞一樣)

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: Caramel
@file: 6.1_merge_sort.py
@time: 2020/02/12
@desc:歸并排序
"""
def merge_sort(alist):
    n = len(alist)
    if n <= 1:
        return alist
    mid = n // 2
    '''采用歸并排序後形成的新的清單'''
    left_li = merge_sort(alist[:mid])
    right_li = merge_sort(alist[mid:])
    '''将兩個有序的子序列合并成一個整體'''
    left_index = 0
    right_index = 0
    result = []
    while left_index < len(left_li) and right_index < len(right_li):
        if left_li[left_index] <= right_li[right_index]:
            '''等号保證穩定性'''
            result.append(left_li[left_index])
            left_index += 1
        else:
            result.append(right_li[right_index])
            right_index += 1
    result += left_li[left_index:]
    result += right_li[right_index:]
    return result
if __name__ == '__main__':
    il = [15, 15, 65, 16, 86, 10, 63]
    print(il)
    sorted = merge_sort(il)
    print(sorted)
           
  • 執行過程

先是對左邊的進行遞歸,分裂直到剩最後一個元素54,然後執行兩個元素[54, 26]的右邊遞歸,得到第一個兩個的右邊元素26

他們兩個執行合并操作,變成[26, 54]。以此類推。

Python資料結構與算法(六)--歸并排序、排序總結、二分查找 歸并排序排序比較 搜尋
  • 執行結束後不是在原有的清單上進行改動,而是在重新生成一個等大的有序清單。雖然時間複雜度降低,但是代價是空間。

排序比較

Python資料結構與算法(六)--歸并排序、排序總結、二分查找 歸并排序排序比較 搜尋

搜尋

  • 二分法查找

前提:

資料已是有序的

操作對象支援下标索引

即是有序順序表

先預處理資料,順序由小到大排列。取中值,關鍵碼與其比較,若果大于就在大的那一部分找,同理。

計算下标時,用第一個和最後一個的下标計算

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: Caramel
@file: 6.2_binary_search.py
@time: 2020/02/12
@desc:二分查找
"""
def binary_search(alist, item):
    '''遞歸'''
    n = len(alist)
    if n >= 2:
        mid = n//2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            return binary_search(alist[:mid], item)
        else:
            return binary_search(alist[mid:], item)
    return False
def binary_search_2(alist, item):
    '''非遞歸'''
    n = len(alist)
    fir = 0
    last = n - 1
    while fir <= last:
        mid = (last + fir) // 2
        if alist[mid] == item:
            return True
        elif item < alist[mid]:
            last = mid - 1
        else:
            fir = mid + 1
    return False
if __name__ == '__main__':
    li = [10, 15, 15, 16, 63, 65, 86]
    print(binary_search(li, 65))
    print(binary_search(li, 98))
    print(binary_search_2(li, 65))
    print(binary_search_2(li, 98))
           

ASL:

log2(n+1)-1

成功檢索:

log2(n+1)向上取整

失敗檢索:

log2(n+1)向上或者向下取整

時間複雜度:

最壞:

O(logn)

最好:

O(1)