基础算法
- 测试执行时间的装饰器:
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
冒泡排序
- 基础版:
import random from timewrap import cal_time @cal_time def bubble_sort(li): for i in range(len(li)-1): # i表示第i趟 for j in range(len(li)-i-1): # j表示箭头位置 if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] li = list(range(1000)) random.shuffle(li) bubble_sort(li) print(li)
- 优化版:
import random from timewrap import cal_time @cal_time def bubble_sort_2(li): for i in range(len(li)-1): # i表示第i趟 exchange = False for j in range(len(li)-i-1): # j表示箭头位置 if li[j] > li[j+1]: li[j], li[j+1] = li[j+1], li[j] exchange = True if not exchange: return li = list(range(1000)) random.shuffle(li) bubble_sort_2(li)
选择排序
import random from timewrap import cal_time @cal_time def select_sort(li): for i in range(len(li) - 1): # i表示第i趟 # 无序区的范围 [i, len(li)) min_pos = i for j in range(i + 1, len(li)): if li[j] < li[min_pos]: min_pos = j li[i], li[min_pos] = li[min_pos], li[i] li = list(range(10000)) random.shuffle(li) print(li) select_sort(li) print(li)
插入排序
-
import random from timewrap import cal_time # 何时插入? 1. j位置的值小于tmp 2.j=-1 li[j+1]=tmp @cal_time def insert_sort(li): for i in range(1, len(li)): j = i-1 tmp = li[i] while j >= 0 and li[j] > tmp: li[j+1] = li[j] j -= 1 li[j+1] = tmp # print(li) li = list(range(10000)) random.shuffle(li) print(li) insert_sort(li) print(li)
快速排序
- 原理:
- 随机找到一个数,让其到排序后的索引处(让一个数先归位);并且让小于他的数到左边,大于他的数到右边
- 递归上面的步骤
- 使用前提:
大于两个元素
- 代码:
import sys import random from timewrap import cal_time sys.setrecursionlimit(1100) 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): _quick_sort(li, 0, len(li)-1) def partition(li, left, right): i = random.randint(left, right) li[left], li[i] = li[i], 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 li = list(range(100000, -1, -1)) random.shuffle(li) quick_sort(li) print(li)
堆排序
-
import random from timewrap import cal_time def sift(li, low, high): # low 表示根位置 high 表示最后元素的位置 tmp = li[low] i = low # i指向空位 j = 2 * i + 1 # j指向孩子 # 把tmp写回来有两种条件 1. tmp > li[j] 2. j位置没有值 (也就是i已经是叶子了) while j <= high: # 对应退出条件2 if j + 1 <= high and li[j + 1] > li[j]: # 如果右孩子存在且右孩子更大 j += 1 if li[j] > tmp: li[i] = li[j] i = j j = 2 * i + 1 else: # 对应退出条件1 break li[i] = tmp @cal_time def heap_sort(li): n = len(li) # 1. 建立堆 for low in range(n // 2 - 1, -1, -1): sift(li, low, n - 1) # print(li) # 2. 挨个出数 退休-棋子-调整 for high in range(n - 1, -1, -1): li[0], li[high] = li[high], li[0] sift(li, 0, high - 1) # print(li) li = list(range(100000)) random.shuffle(li) print(li) heap_sort(li) print(li)
归并排序
-
import random from timewrap import cal_time def merge(li, low, mid, high): li_tmp = [] i = low j = mid + 1 while i <= mid and j <= high: if li[i] <= li[j]: li_tmp.append(li[i]) i += 1 else: li_tmp.append(li[j]) j += 1 while i <= mid: li_tmp.append(li[i]) i += 1 while j <= high: li_tmp.append(li[j]) j += 1 for i in range(len(li_tmp)): li[i + low] = li_tmp[i] def _merge_sort(li, low, high): if low < high: # 2个元素及以上 mid = (low + high) // 2 _merge_sort(li, low, mid) _merge_sort(li, mid + 1, high) merge(li, low, mid, high) @cal_time def merge_sort(li): _merge_sort(li, 0, len(li) - 1) li = list(range(100000)) random.shuffle(li) merge_sort(li)