Python之實現常見算法


一、 算法是什么?
    算法是指解題方案的准確而完整的描述,是一系列解決問題的清晰指令,算法代表着用系統的方法描述解決問題的策略機制。也就是說,能夠對一定規范的輸入,在有限時間內獲得所要求的輸出。如果一個算法有缺陷,或不適合於某個問題,執行這個算法將不會解決這個問題。不同的算法可能用不同的時間、空間或效率來完成同樣的任務。一個算法的優劣可以用空間復雜度與時間復雜度來衡量。


二、 時間復雜度:
    時間復雜度是用來估計算法運行時間的一個式子(單位)
    一般來說*,時間復雜度高的算法比復雜度低的算法慢
    
    常見時間復雜度單位:效率從上到下變低,
        O(1)    簡單的一次運算
        O(logn)    循環減半
        O(n)    一次循環
        O(nlogn)    一個循環加一個循環減半
        O(n^2)     兩個循環
        O(n^2logn)
        O(n^3)
        
    如何一眼判斷時間復雜度?
        循環減半的過程àO(logn)
        幾次循環就是n的幾次方的復雜度
    

三、 空間復雜度
    空間復雜度是用來評估算法內存占用大小的單位
    
    空間換時間:如果需要增快算法的速度,需要的空間會更大

 

四、python實現常見的算法

  1、冒泡(交換)排序

    原理:列表中兩個相鄰的數,如果前一個數比后一個數大,就做交換。一共需要遍歷列表的次數是len(lst)-1

    時間復雜度:O(n^2)

def bubble_sort(lst):
    for i in range(len(lst)-1):     # 這是需要循環遍歷多少次
        for j in range(len(lst)-i-1):   # 每次數組中的無序區
            if lst[j] >lst[j+1]:
                lst[j],lst[j+1] = lst[j+1],lst[j]

lst = [1, 2, 44, 3, 5]
bubble_sort(lst)
print(lst)

  

    優化:如果在循環的時候,有一次沒有進行交換,就表示數列中的數據已經是有序的
     時間復雜度:最好情況是0(n),只遍歷一次,一般情況和最壞情況都是O(n^2)

def bubble_sort(lst):
    for i in range(len(lst)-1):     # 這是需要循環遍歷多少次
        change = False      # 做一個標志變量
        for j in range(len(lst)-i-1):   # 每次數組中的無序區
            if lst[j] >lst[j+1]:
                lst[j],lst[j+1] = lst[j+1],lst[j]
                change = True   # 每次遍歷,如果進來排序的話,就會改變change的值
        if not change:  # 如果change沒有改變,那就表示當前的序列是有序的,直接跳出循環即可
            return


lst = [1, 2, 44, 3, 5]
bubble_sort(lst)
print(lst)

  

  2、選擇排序

    原理:每次遍歷找到當下數組最小的數,並把它放到第一個位置,下次遍歷剩下的無序區

def select_sort(lst):
    for i in range(len(lst) - 1):    # 當前需遍歷的次數
        min_loc = i     # 當前最小數的位置
        for j in range(i+1, len(lst)):   # 無序區
            if lst[j] < lst[min_loc]:     # 如果有更小的數
                min_loc = j     # 最小數的位置改變
        if min_loc != i:
            lst[i], lst[min_loc] = lst[min_loc], lst[i]     # 把最小數和無序區第一個數交換交換

lst = [1, 2, 44, 3, 5]
select_sort(lst)
print(lst)

  

  3、插入排序

    原理:列表分為有序區和無序區,有序區是一個相對有序的序列,認為一開始的時候有序區有一值,每次從無序區選擇一個值,放到有序區,直到無序區為空

def insert_sort(lst):
    for i in range(1,len(lst)):     # 從1開始遍歷表示無序區從1開始,有序區初始有一個值
        tmp = lst[i]    # tmp表示拿到的無序區的第一張牌
        j = i - 1   # j表示有序區的最后一個值
        while j >= 0 and lst[j] > tmp:  # 當有序區有值,並且有序區的值比無序區拿到的值大就一直循環
            lst[j+1] = lst[j]   # 有序區的值往后移
            j -= 1  # 找到上一個有序區的值,然后再循環
        lst[j+1] = tmp  # 跳出循環之后,只有j+1的位置是空的,要把當下無序區的值放到j+1的位置

lst = [1, 2, 44, 3, 5]
insert_sort(lst)
print(lst)

  

    二分插入:實際上並沒有優化的效果

def insert_sort(lst):
    for i in range(1, len(lst)):
        left = 0
        right = i - 1
        tmp = lst[i]
        while left <= right:
            mid = (left + right) / 2
            if tmp >= lst[mid]:
                left = mid + 1
            if tmp < lst[mid]:
                right = mid - 1
        for j in range(i - 1, left - 1, -1):  # [i-1,left]
            lst[j + 1] = lst[j]
        lst[left] = tmp

    return lst

  

  4、快速排序

    思路:取第一個元素,讓它歸位,就是放到一個位置,使它左邊的都比它小,右邊的都比它大,然后遞歸(先歸位,后遞歸)

    時間復雜度:O(nlog(n))

    最壞情況:

      最壞情況下的事件復雜度是O(n2)

      標志數的左邊或者右邊只有一個數

       解決方法:不要找第一個元素,隨機找一個元素

def parttion(lst, left, right):
    i = left
    j = right
    tmp = lst[i]    # 把此次循環的標志數存起來
    while i < j:
        while i < j and lst[j] > tmp:   # 先從右邊開始找比標志數小的,有的話跳出循環
            j -= 1
        lst[i] = lst[j] # 跳出循環之后,把這個比標志數小的值放到標志數的位置
        while i < j and lst[i] < tmp:   # 左邊的排序方法和右邊一樣
            i += 1
        lst[j] = lst[i]
    lst[i] = tmp    # 整個排序結束之后,把一開始的標志數放回空位
    return i


def quick_sort(lst, left, right):
    if left < right:    # 至少有兩個元素
        p = parttion(lst, left, right)
        quick_sort(lst, left, p-1)
        quick_sort(lst, p+1, right)
        

lst = [1, 2, 44, 3, 5]
quick_sort(a, 0, 4)
print(lst)

  

 


免責聲明!

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



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