什麼是算法?算法
算法:一個計算過程,解決問題的方法數據結構
一個大牛曾說過:程序=數據結構+算法app
遞歸的兩個特色:dom
調用自身ide
結束條件ui
下面兩個的不一樣: spa
# def func3(x): # if x>0: # print(x) # func3(x-1) # func3(5)這個打印的結果是54321 def func4(x): if x > 0: func4(x - 1) print(x) func4(5)#這個打印的結果是12345
咱們來看代碼運行的時間複雜度和空間複雜度:code
時間複雜度:blog
print('Hello World!')#這個時間的複雜度是o(1)排序
for i in range(n):
print('Hello World') #z這個時間的複雜度是o(n)
for i in range(n):
for j in range(n):
print('Hello World!')#這個時間的複雜度是o(n2)
while n>1:
print(n)
n=n//2 #這個時間的複雜度是O(logn)
時間複雜度小結:
時間複雜度是用來估計算法運行時間的一個式子(單位)。
通常來講,時間複雜度高的算法比複雜度低的算法慢。
常見的時間複雜度(按效率排序):
如何一眼判斷時間複雜度?
循環減半的過程就是O(logn)
幾回循環就是n的幾回方複雜度。
空間複雜度:
它是用來評估算法內存佔用大小的一個式子
遞歸查找的二分法:
def linear_search(data_set,value):#時間複雜度是O(n) for i in range(range(data_set)): if data_set[i]==value: return i return def bin_search(data_set,value):#時間複雜度是O(logn) low=0 high=len(data_set)-1 while low<=high: mid=(low+high)//2 if data_set[mid]==value: return mid elif data_set[mid]>value: high=mid-1 else: low=mid+1
遞歸版的二分查找:
def bin_search_rec(data_set,value,low,high): if low <= high: mid=(low+high)//2 if data_set[mid]==value: return mid elif data_set[mid]>value: return bin_search_rec(data_set,value,low,mid-1) else: return bin_search_rec(data_set,value,mid+1,high) else: return li=[55,66,77,88,99,100,200,600,500] s=bin_search_rec(li,100,0,len(li)-1) print(s)
排序模塊:
排序屆lowB三人組:
冒泡排序
import random def bubble_sort_2(li):#時間複雜度是O(n*2) for i in range(len(li) - 1): # i 表示趟數 # 第 i 趟時: 無序區:(0,len(li) - i) change = False for j in range(0, len(li) - i - 1): if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] change = True if not change: return li = list(range(10000))#生成一個列表 random.shuffle(li)#打亂列表 print(li) bubble_sort_2(li)#冒泡排序 print(li)
選擇排序
import random def select_sort(li): for i in range(len(li) - 1): # i 表示趟數,也表示無序區開始的位置 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] li = list(range(10)) random.shuffle(li) print(li) select_sort(li) print(li)
插入排序
import random def insert_sort(li): for i in range(1, len(li)): # i 表示無序區第一個數 tmp = li[i] # 摸到的牌 j = i - 1 # j 指向有序區最後位置 while li[j] > tmp and j >= 0: #循環終止條件: 1. li[j] <= tmp; 2. j == -1 li[j+1] = li[j] j -= 1 li[j+1] = tmp li = list(range(10)) random.shuffle(li) print(li) insert_sort(li) print(li)
NB排序方法:
import time def cal_time(func): def wrapper(*args, **kwargs): t1 = time.time() result = func(*args, **kwargs) t2 = time.time() print("%s running time: %s secs." % (func.__name__, t2-t1)) return result return wrapper
快排
# def partition(li, left, right): # temp = li[left] # while left < right: # while left < right and li[right] >= temp: # right -= 1 # li[left] = li[right] # while left < right and li[left] <= temp: # left += 1 # li[right] = li[left] # # li[left] = temp # return left # def partition(li, left, right): # # ri = random.randint(left, right) # # li[left], li[ri] = li[ri], li[left] # tmp = li[left] # while left < right: # while left < right and li[right] >= tmp: # right -= 1 # li[left] = li[right] # while left < right and li[left] <= tmp: # left += 1 # li[right] = li[left] # li[left] = tmp # return left # def quick_sort(li, left, right): # if left < right: # mid = partition(li, left, right) # # quick_sort(li, left, mid - 1) # # quick_sort(li, mid + 1, right) # # # li = list(range(100)) # li.reverse() # print(li) # quick_sort(li, 0, len(li) - 1) # print(li) import random from timewrap import * import copy import sys sys.setrecursionlimit(100000) # 設置最大遞歸深度 def partition(li, left, right): ri = random.randint(left, right) # 加上這個是爲了防止最壞的狀況出現 li[left], li[ri] = li[ri], li[left] tmp = li[left] while left < right: while left < right and li[right] >= tmp: right -= 1 li[left] = li[right] while left < right and li[left] <= tmp: left += 1 li[right] = li[left] li[left] = tmp return left # 返回歸併的的索引 def _quick_sort(li, left, right): if left < right: # 至少有兩個元素 mid = partition(li, left, right) _quick_sort(li, left, mid - 1) _quick_sort(li, mid + 1, right) @cal_time def quick_sort(li): return _quick_sort(li, 0, len(li) - 1) @cal_time def sys_sort(li): li.sort() li = list(range(100000)) random.shuffle(li)#這是打亂列表的順序 li.reverse() li1 = copy.deepcopy(li) li2 = copy.deepcopy(li) sys_sort(li1) # 0.17502140998840332 secs.系統使用C寫的比較快 quick_sort(li2) # quick_sort running time: 0.0004992485046386719 secs. # print(li)
堆排序:
from timewrap import * import random def _sift(li, low, high): """ :param li: :param low: 堆根節點的位置 :param high: 堆最後一個節點的位置 :return: """ i = low # 父親的位置 j = 2 * i + 1 # 孩子的位置 tmp = li[low] # 原省長 while j <= high: if j + 1 <= high and li[j + 1] > li[j]: # 若是右孩子存在而且右孩子更大 j += 1 if tmp < li[j]: # 若是原省長比孩子小 li[i] = li[j] # 把孩子向上移動一層 i = j j = 2 * i + 1 else: li[i] = tmp # 省長放到對應的位置上(幹部) break else: li[i] = tmp # 省長放到對應的位置上(村民/葉子節點) def sift(li, low, high): """ :param li: :param low: 堆根節點的位置 :param high: 堆最有一個節點的位置 :return: """ i = low # 父親的位置 j = 2 * i + 1 # 孩子的位置 tmp = li[low] # 原省長 while j <= high: if j + 1 <= high and li[j+1] > li[j]: # 若是右孩子存在而且右孩子更大 j += 1 if tmp < li[j]: # 若是原省長比孩子小 li[i] = li[j] # 把孩子向上移動一層 i = j j = 2 * i + 1 else: break li[i] = tmp @cal_time def heap_sort(li): n = len(li) # 1. 建堆 for i in range(n//2-1, -1, -1): sift(li, i, n-1) # 2. 挨個出數 for j in range(n-1, -1, -1): # j表示堆最後一個元素的位置 li[0], li[j] = li[j], li[0] # 堆的大小少了一個元素 (j-1) sift(li, 0, j-1) li = list(range(10000)) random.shuffle(li) heap_sort(li) print(li) # li=[2,9,7,8,5,0,1,6,4,3] # sift(li, 0, len(li)-1) # print(li)
歸併排序
import random from timewrap import * import copy import sys def merge(li, low, mid, high): i = low j = mid + 1 ltmp = [] while i <= mid and j <= high: if li[i] < li[j]: ltmp.append(li[i]) i += 1 else: ltmp.append(li[j]) j += 1 while i <= mid: ltmp.append(li[i]) i += 1 while j <= high: ltmp.append(li[j]) j += 1 li[low:high+1] = ltmp def _merge_sort(li, low, high): if low < high: # 至少兩個元素 mid = (low + high) // 2 _merge_sort(li, low, mid) _merge_sort(li, mid+1, high) merge(li, low, mid, high) # print(li[low:high+1]) def merge_sort(li): return _merge_sort(li, 0, len(li)-1) li = list(range(16)) random.shuffle(li) print(li) # li=[10,8,11,7] # merge_sort(li) # # print(li)
NB算法的時間複雜度都是O(nlongn):
通常狀況下:就運行時間而言:
快速排序<歸併排序<堆排序
三種排序算法的缺點:
快速排序:極端狀況下排序效率低
歸併排序:須要額外的內存開銷
堆排序:在快的排序算法中相對較慢