算法
遞歸兩個特點:
調用自身
有窮調用
計算規模越來越小,直至最后結束
用裝飾器修飾一個遞歸函數時會出現問題,這個問題產生的原因是遞歸的函數也不停的使用裝飾器。
解決方法是,只讓裝飾器調用一次即可,那么可以出創建一個新的普通函數,執行一下遞歸函數,並放回遞歸函數的返回值,給這個普通函數加上裝飾器即可。
尾遞歸和正常循環時間復雜度相同,尾遞歸:每次遞歸尾部return遞歸函數
算法關鍵:
有序區和無序區,隨着算法的推進,有序區越來越大,無序區越來越小,直至消失,完成排序
代碼:
import random
import time
import sys
import copy
#裝飾器
def time_cost(func):
def wrapper(*args,**kwargs):
sTime = time.time()
func(*args,**kwargs)
print("Time cost:%s"%(time.time()-sTime))
print(args[0])
return wrapper
#冒泡排序:
#每一次循環從端點處比較n次選出最大或最小的數,一趟結束n--,每次里層循環n-i-1次。
@time_cost def bubble_sort(list): print("\nbubble_sort:") for i in range(len(list)-1): tag = 0 for j in range(len(list)-i-1): if list[j] > list[j+1]: list[j],list[j+1] = list[j+1],list[j] tag = 1 if not tag: return
#選擇排序
#每次選出最小的數,放在n,每趟結束n++,每次里層循環(i+1,len(list))
@time_cost def select_sort(list): print("\nselect_sort:") for i in range(len(list)-1): min = i for j in range(i+1,len(list)): if list[min] > list[j]: min = j if min != i: list[i],list[min] = list[min],list[i]
#插入排序
#分有序區和無序區,列表前面是有序區,后面是無序區,每次從無序區的首位取一個元素,與有序區元素依次比較,放到合適的位置,直到無序區元素取完
@time_cost def insert_sort(list): print("\ninsert_sort:") for i in range(len(list)): tag = 0 for j in range(i,0,-1): if list[j] < list[j-1]: list[j],list[j-1] = list[j-1],list[j] tag = 1 if not tag: break
#快速排序
#遞歸實現,取一個數(列表第一個),使得列表左邊的元素比此數都小,列表右邊的元素比此數都大,依據此數位置切割出左右兩邊列表分別進行遞歸,直至列表只有一個元素
def part_sort(list,left,right): temp = list[left] while left < right: while left < right and temp <= list[right]: right -= 1 list[left] = list[right] while left < right and temp >= list[left]: left += 1 list[right] = list[left] list[left] = temp return left def _quckly_sort(list,left,right): if left < right: mid = part_sort(list,left,right) _quckly_sort(list,left,mid-1) _quckly_sort(list,mid+1,right) @time_cost def quckly_sort(list): print("\nquckly_sort:") return _quckly_sort(list,0,len(list)-1)
#快排的時間復雜度為O(nlogn)
#冒泡、選擇、插入排序的時間復雜度為O(n^2)
#一般來說處理大數據排序問題,快排比前面三種排序快好幾個數量級
#但是如果碰到極端情況,例如:列表是反序排列的
#快排的時間復雜度退化成O(n^2)
#由於自身有遞歸加大開銷,會使相同排序比其他三種排序耗時更久
#系統自帶排序 sort()
#大多數編程語言系統排序使用的都是快速排序
#python系統自帶的排序使用的是C語言編寫的快排,比python寫的快排快一個數量級
sort(list)
#一般來說系統都有限制最大遞歸層數
#修改系統最大遞歸層數
import sys
sys.setrecursionlimit(10000)
#比較4種排序,當排序個數為10000時
#bubble_sort:
#Time cost:17.794017791748047
#select_sort:
#Time cost:5.8113322257995605
#insert_sort:
#Time cost:15.441883087158203
#_quckly_sort:
#Time cost:0.044002532958984375
#快排效率非常高
#堆排序
#當各節點是順序存儲時,且必須是完全二叉樹
#父節點與左孩子關系: i ~ 2i+1
#父節點與右孩子關系: i ~ 2i+2
#首先將列表元素建堆,形成大根堆
#然后循環調整大根堆,取堆頂元素,生成有序序列
#時間復雜度O(nlogn)
def sift(list,low,high): i = low j = 2 * i + 1 temp = list[i] while j <= high: if j < high and list[j] < list[j+1]: j += 1 if temp < list[j]: list[i] = list[j] i = j j = 2 * i + 1 else: break list[i] = temp list[low],list[high] = list[low],list[high] @time_cost def heap_sort(list): print("\nheap_sort:") n = len(list) for i in range(n // 2 - 1, -1, -1): sift(list, i, n - 1) for i in range(n-1, -1, -1): list[0],list[i] = list[i],list[0] sift(list, 0, i - 1)
#歸並排序
#一次歸並,將兩個排序好的列表合並成一個有序列表
#首先將一個無序列表遞歸分解成只有1個元素的n個列表
#將所有分解的列表兩兩執行一次歸並算法,最終合成一個有序列表
#時間復雜度O(nlogn)
#空間復雜度O(n)每個一次歸並都創建一個列表
def ont_megre_sort(list,low,mid,high): i = low j = mid + 1 ltmp = [] while i <= mid and j <= high: if list[i] < list[j]: ltmp.append(list[i]) i += 1 else: ltmp.append(list[j]) j += 1 while i <= mid: ltmp.append(list[i]) i += 1 while j <= high: ltmp.append(list[j]) j += 1 list[low:high+1] = ltmp def _megre_sort(list,low,high): if low < high: mid = (low+high)//2 _megre_sort(list,low,mid) _megre_sort(list,mid+1,high) ont_megre_sort(list,low,mid,high) @time_cost def megre_sort(list): print("\nmegre_sort:") return _megre_sort(list,0,len(list)-1)
#一般來說 快速排序 < 歸並排序 < 堆排序
#快排極端情況下速度慢,不穩定
#歸並排序需要空間開銷
#堆排序相對穩定
#時間復雜度O(n)
#希爾排序
#一種分組插入排序算法
#根據定義d為間隔分組,對每個小分組做一次直接插入排序
#d逐漸縮小,列表相對有序,直至d=1,成為直接插入排序,最后一次循環使列表徹底有序
#時間復雜度O((1+T)n)=O(1.3n)
@time_cost def shell_sort(list): print("\nshell_sort:") gap = len(list) // 2 while gap > 0: for i in range(gap,len(list)): temp = list[i] j = i - gap while j >= 0 and temp < list[j]: list[j + gap] = list[j] j -= gap list[j + gap] = temp gap //= 2
#----------------------------------------------總結------------------------------------------------#
# 排序方法 時間復雜度 穩定性 代碼復雜度 #
# #
# 最壞情況 平均情況 最好情況 #
# 冒泡排序 O(n^2) O(n^2) O(n) 穩定 簡單 #
# #
# 直接選擇排序 O(n^2) O(n^2) O(n^2) 不穩定 簡單 #
# #
# 直接插入排序 O(n^2) O(n^2) O(n^2) 穩定 簡單 #
# #
# 快速排序 O(n^2) O(nlogn) O(nlogn) 不穩定 較復雜 #
# #
# 堆排序 O(nlogn) O(nlogn) O(nlogn) 穩定 復雜 #
# #
# 歸並排序 O(nlogn) O(nlogn) O(nlogn) 穩定 較復雜 #
# #
# 希爾排序 O(1.3n) 不穩定 較復雜 #
# #
# #
#-----------------------------------------------------------------------------------------------------------------------------#
全部代碼
__author__ = 'cq' import time import random import sys import copy def time_cost(func): def wrapper(*args,**kwargs): sTime = time.time() func(*args,**kwargs) print("Time cost:%s"%(time.time()-sTime)) print(args[0]) return wrapper #-------------------冒泡排序-----------------------# @time_cost def bubble_sort(list): print("\nbubble_sort:") for i in range(len(list)-1): tag = 0 for j in range(len(list)-i-1): if list[j] > list[j+1]: list[j],list[j+1] = list[j+1],list[j] tag = 1 if not tag: return #-------------------插入排序-----------------------# @time_cost def insert_sort(list): print("\ninsert_sort:") for i in range(len(list)): tag = 0 for j in range(i,0,-1): if list[j] < list[j-1]: list[j],list[j-1] = list[j-1],list[j] tag = 1 if not tag: break #-------------------選擇排序-----------------------# @time_cost def select_sort(list): print("\nselect_sort:") for i in range(len(list)-1): min = i for j in range(i+1,len(list)): if list[min] > list[j]: min = j if min != i: list[i],list[min] = list[min],list[i] #-------------------快速排序-----------------------# def part_sort(list,left,right): temp = list[left] while left < right: while left < right and temp <= list[right]: right -= 1 list[left] = list[right] while left < right and temp >= list[left]: left += 1 list[right] = list[left] list[left] = temp return left def _quckly_sort(list,left,right): if left < right: mid = part_sort(list,left,right) _quckly_sort(list,left,mid-1) _quckly_sort(list,mid+1,right) @time_cost def quckly_sort(list): print("\nquckly_sort:") return _quckly_sort(list,0,len(list)-1) #-------------------堆排序-----------------------# def sift(list,low,high): i = low j = 2 * i + 1 temp = list[i] while j <= high: if j < high and list[j] < list[j+1]: j += 1 if temp < list[j]: list[i] = list[j] i = j j = 2 * i + 1 else: break list[i] = temp list[low],list[high] = list[low],list[high] @time_cost def heap_sort(list): print("\nheap_sort:") n = len(list) for i in range(n // 2 - 1, -1, -1): sift(list, i, n - 1) for i in range(n-1, -1, -1): list[0],list[i] = list[i],list[0] sift(list, 0, i - 1) #-------------------歸並排序-----------------------# def ont_megre_sort(list,low,mid,high): i = low j = mid + 1 ltmp = [] while i <= mid and j <= high: if list[i] < list[j]: ltmp.append(list[i]) i += 1 else: ltmp.append(list[j]) j += 1 while i <= mid: ltmp.append(list[i]) i += 1 while j <= high: ltmp.append(list[j]) j += 1 list[low:high+1] = ltmp def _megre_sort(list,low,high): if low < high: mid = (low+high)//2 _megre_sort(list,low,mid) _megre_sort(list,mid+1,high) ont_megre_sort(list,low,mid,high) @time_cost def megre_sort(list): print("\nmegre_sort:") return _megre_sort(list,0,len(list)-1) #-------------------希爾排序-----------------------# @time_cost def shell_sort(list): print("\nshell_sort:") gap = len(list) // 2 while gap > 0: for i in range(gap,len(list)): temp = list[i] j = i - gap while j >= 0 and temp < list[j]: list[j + gap] = list[j] j -= gap list[j + gap] = temp gap //= 2 def main(): #生成列表 list0 = list(range(100)) first_name = ["陳","張","李","王","趙"] second_name = ["冰","鑫","程","愛","暖"] third_name = ["強","國","明","風","芬"] listname = [ {"id":"1000"+str(i), "name":random.choice(first_name)+ random.choice(second_name)+ random.choice(third_name), "age":random.randint(16,60) } for i in range(10) ] random.shuffle(list0) random.shuffle(listname) #copy四份打亂后的列表 list1 = copy.deepcopy(list0) list2 = copy.deepcopy(list0) list3 = copy.deepcopy(list0) list4 = copy.deepcopy(list0) list5 = copy.deepcopy(list0) list6 = copy.deepcopy(list0) list7 = copy.deepcopy(list0) #設置遞歸深度 sys.setrecursionlimit(10000) print("sort_list:") print(list0) #排序算法 bubble_sort(list1) select_sort(list2) insert_sort(list3) quckly_sort(list4) heap_sort(list5) megre_sort(list6) shell_sort(list7) print("\npractice to sort this list:") for i in listname: print(i) if "__main__" == __name__: main()
