Python開發【二十八章】:演算法,python二十八章

來源:互聯網
上載者:User

Python開發【二十八章】:演算法,python二十八章
演算法基礎

1、什麼是演算法?

演算法(Algorithm):一個計算過程,解決問題的方法

 

2、複習:遞迴

遞迴的兩個特點:

  • 調用自身
  • 結束條件

兩個重要遞迴函式的對比:

# 由大到小def func3(x):    if x > 0 :        print(x)        func3(x-1)# func3(5)# 5 4 3 2 1# 由小到大def func4(x):    if x > 0 :        func4(x-1)        print(x)func4(5)# 1 2 3 4 5

  

3、時間複雜度

時間複雜度:用來評估演算法運行效率的一個東西:

print('Hello World')            # 0(1)for i in range(n):                  # O(n)    print('Hello World')for i in range(n):                   # O(n^2)    for j in range(n):        print('Hello World')for i in range(n):                   # O(n^3)    for j in range(n):        for k in range(n):            print('Hello World')

第一個列印了一次時間複雜度為O(1);第二個列印了n次,所以時間複雜度為O(n);第三四個依次為n²和n的3次方

那麼看看下面代碼中的時間複雜度為多少?

# 非O(3) 而是O(1)print('Hello World')print('Hello Python')print('Hello Algorithm')# 非O(n²+n) 而是O(n²)for i in range(n):    print('Hello World')        for j in range(n):            print('Hello World')# 非O(1/2n²) 而是O(n2)for i in range(n):    for j in range(i):         print('Hello World')

再看看下面代碼: 

# 時間複雜度 O(log2n) 或 O(logn)while n > 1:    print(n)    n = n // 2# n=64輸出:# 64# 32# 16# 8# 4# 2

小結:

時間複雜度是用來估計演算法已耗用時間的一個式子(單位)。

一般來說,時間複雜度低的演算法比複雜度低的演算法快。

常見的時間複雜度(按用時排序)

  • O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)

不常見的時間複雜度(看看就好)

  • O(n!) O(2n) O(nn) …

如何一眼判斷時間複雜度?

  • 迴圈減半的過程O(logn)
  • 幾次迴圈就是n的幾次方的複雜度

 

4、空間複雜度

空間複雜度:用來評估演算法記憶體佔用大小的一個式子

 

列表尋找

列表尋找:從列表中尋找指定元素

  • 輸入:列表、待尋找元素
  • 輸出:元素下標或未尋找到元素

1、順序尋找

從列表第一個元素開始,順序進行搜尋,直到找到為止

def linear_search(data_set, value):      for i in data_set:               if data_set[i] == value:                return i      return

時間複雜度為O(n)

 

2、二分尋找

從有序列表的候選區data[0:n]開始,通過對待尋找的值與候選區中間值的比較,可以使候選區減少一半

# 正宗的二分尋找data = [i for i in range(9000000)]import timedef cal_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re =  func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return inner@cal_timedef bin_search(data_set,val):    low = 0    high = len(data_set) - 1    while low <= high:        mid = (low + high)//2        if data_set[mid] == val:            return mid        elif data_set[mid] < val:            low = mid +1        else:            high = mid -1bin_search(data, 999)# Time cost: bin_search 0.0005002021789550781

時間複雜度為O(logn),運行後會發現執行的很快,下面對比下之前Alex講過的二分尋找

# Alex的low版本data = [i for i in range(9000000)]import timedef cal_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re =  func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return innerdef _binary_search(dataset, find_num):    if len(dataset) > 1:        mid = int(len(dataset) / 2)        if dataset[mid] == find_num:  # find it            print("找到數字", dataset[mid])        elif dataset[mid] > find_num:  # 找的數在mid左面            return _binary_search(dataset[0:mid], find_num)        else:  # 找的數在mid右面            return _binary_search(dataset[mid + 1:], find_num)@cal_timedef binary_search(dataset, find_num):    _binary_search(dataset, find_num)binary_search(data, 999)# Time cost: binary_search 0.4435563087463379

 

3、練習  

現有一個學員資訊列表(按id增序排列),格式為:

[{id:1001, name:"張三", age:20},{id:1002, name:"李四", age:25},{id:1004, name:"王五", age:23},{id:1007, name:"趙六", age:33}]

修改二分尋找代碼,輸入學生id,輸出該學生在列表中的下標,並輸出完整學生資訊

import randomimport time# 產生隨機列表def  random_list(n):    result = []    ids = list(range(1001,1001+n))    n1 = ['趙','王','孫','李']    n2 = ['國','愛','清','菲','']    n3 = ['甄','軒','雨','軍']    for i in range(n):        age = random.randint(18,60)        id = ids[i]        name = random.choice(n1)+random.choice(n2)+random.choice(n3)        dic = {'id':id,'name':name,'age':age}        result.append(dic)    return result# 二分尋找def cal_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re =  func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return inner@cal_timedef bin_search(data_set,val):    low = 0    high = len(data_set) - 1    while low <= high:        mid = (low + high)//2        if data_set[mid]['id'] == val:            return mid        elif data_set[mid]['id'] < val:            low = mid +1        else:            high = mid -1student_list = random_list(100000)bin_search(student_list, 999)# Time cost: bin_search 0.0004999637603759766
學員id查詢.py

 

列表排序

概述

列表排序:

將無序列表變為有序列表

應用情境:

  • 各種榜單
  • 各種表格
  • 給二分排序用
  • 給其他演算法用
排序low B三人組:冒泡排序選擇排序插入排序快速排序排序NB二人組:堆排序歸併排序沒什麼人用的排序:基數排序希爾排序桶排序
幾種排序的對比

 

1、冒泡排序(low)

排序思路:首先,列表每兩個相鄰的數,如果前邊的比後邊的大,那麼交換這兩個數,每次迴圈都會選中一個最大的數,然後依次把列表排序;

import randomimport timedef call_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re = func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return inner@call_timedef bubble_sort(data):    for i in range(len(data)-1):        for j in range(len(data)-i-1):            if data[j] > data[j+1]:                data[j],data[j+1] = data[j+1],data[j]    return datadata = list(range(10000))random.shuffle(data)bubble_sort(data)# Time cost: bubble_sort 17.608235836029053

時間複雜度:O(n²)

最佳化:

@call_timedef bubble_sort_1(data):    for i in range(len(data)-1):        exchange = False                # 沒有交換 表示前邊都已經排好了 執行退出        for j in range(len(data)-i-1):            if data[j] > data[j+1]:                data[j],data[j+1] = data[j+1],data[j]                exchange = True        if not exchange:            break    return data

  

2、選擇排序(low)

排序思路:一趟遍曆記錄最小的數,放到第一個位置; 再一趟遍曆記錄剩餘列表中最小的數,繼續放置;或遍曆最大的放到最後

import randomimport timedef call_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re = func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return inner@call_timedef select_sort(li):    for i in range(len(li)-1):        max_loc = 0        for j in range(len(li)-i-1):            if li[max_loc] < li[j]:                max_loc = j        li[len(li)-i-1],li[max_loc] = li[max_loc],li[len(li)-i-1]data = list(range(10000))random.shuffle(data)select_sort(data)# Time cost: select_sort 10.837876319885254

時間複雜度:O(n²)  

def select_sort(li):    for i in range(len(li)-1):        min_loc = i        for j in range(i+1,len(li)):            if li[j] < li[min_loc]:                min_loc = j        li[i],li[min_loc] = li[min_loc],li[i]
從前面開始排

 

3、插入排序(low)

插入思路:列表被分為有序區和無序區兩個部分。最初有序區只有一個元素。 每次從無序區選擇一個元素,插入到有序區的位置,直到無序區變空

import randomimport timedef call_time(func):    def inner(*args,**kwargs):        t1 = time.time()        re = func(*args,**kwargs)        t2 = time.time()        print('Time cost:',func.__name__,t2-t1)        return re    return inner@call_timedef insert_sort(li):    for i in range(1,len(li)):        for k in range(i-1,-1,-1):            if li[i] < li[k]:                li[i],li[k] = li[k],li[i]                i = k            else:                breakdata = list(range(10000))random.shuffle(data)insert_sort(data)# Time cost: insert_sort 9.358688592910767

時間複雜度:O(n²)  

def insert_sort(li):    for i in range(1,len(li)):        tmp = li[i]        j = i -1         while j >=0 and li[j] > tmp:            li[j+1] = li[j]            j = j -1        li[j+1] = tmp
老師的寫法

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.