程序=数据结构+算法
递归(复习)
特点:
调用自身
结束条件
def func1(x):
if x>0:
func1(x-1)
print(x)
func1(10)
列表查找
顺序查找:就是for循环,一个一个找
二分查找:必须是有序的列表
代码:
1 def bin_search(li,val): 2 low = 0 3 high = len(li) -1 4 while low <=high: 5 mid = (low+high)//2 6 if li[mid] ==val: 7 return mid 8 elif li[mid] >val: 9 high = mid -1 10 else: 11 low = mid +1 12 return None 13 li=list(range(1000)) 14 print(bin_search(li,3))
LOW B三人组
冒泡:列表每两个相邻的数,如果前面比后面的大,那么交换这两个数的位置
选择:一趟遍历记录中最小的数,放到第一个位置,再一趟遍历剩余列表中的数字,继续放置
插入:每次从无序区选择一个元素,插入到有序区,直到无序区为空
冒泡代码:
1 def bubble_sort(li): 2 for i in range(len(li)-1): 3 flag = False 4 for j in range(0, len(li)-i-1): 5 if li[j] > li[j+1]: 6 li[j], li[j+1] = li[j+1], li[j] 7 flag=True 8 if not flag: #如果走了一趟都没有变化,说明已经排好了,直接跳出循环 9 break 10 11 li=list(range(100)) 12 random.shuffle(li) 13 print(li) 14 bubble_sort(li) 15 print(li)
选择排序代码:
1 def select_sort(li): 2 for i in range(len(li)-1): 3 min_loc = i 4 for j in range(i+1, len(li)): #该循环总能找到最小值 5 if li[j] < li[min_loc]: 6 min_loc = j 7 li[min_loc], li[i] = li[i], li[min_loc] 8 9 li=list(range(100)) 10 random.shuffle(li) 11 print(li) 12 select_sort(li) 13 print(li)
插入排序代码
1 def insert_sort(li): 2 for i in range(1, len(li)):#从第二个开始循环 3 tmp = li[i] #把抽到的牌先临时存起来 4 j = i - 1 #前面那张牌的下标 5 while j>=0 and li[j]>tmp: #从第二个开始循环,且前面的数大于后面 6 li[j+1]=li[j] #满足条件j的位置往后挪一位,tmp不插入 7 j = j - 1 #再把前一张牌往前挪一位,去比较下一张 8 li[j+1] = tmp #插入tmp 9 10 li=list(range(100)) 11 random.shuffle(li) 12 print(li) 13 insert_sort(li) 14 print(li)
NB三人组
快排:好写排序里面最快的
取一个元素P,通过某种方式使P归位,列表被分成两部分,左边的都比P小,右边的都比P大,完成归位;
分别对左右递归,当列表中小于两个元素,排序完成。
代码:
def partition(data, left, right):
tmp = data[left] #取第一个数(要归位的数)临时存起来,此时左边有空位了
while left < right:
while left<right and data[right] >= tmp: #从右边找只要right比tmp大,就一直找
right -= 1
data[left]=data[right] #不满足while条件,说明右边比左边小,将右边的数值,覆盖到左边
while left<right and data[left] <= tmp: #从左边找
left += 1
data[right]=data[left]
data[left]=tmp #不满足while条件,说明left=fight,归位
return left
def quick_sort_x(data, left, right):
if left < right:#说明至少还有俩元素,需要继续递归
mid = partition(data, left, right) #mid值指已经归位的下标,把列表分成两部分
quick_sort_x(data, left, mid - 1)
quick_sort_x(data, mid + 1, right)
@cal_time
def quick_sort(data):
quick_sort_x(data, 0, len(data)-1)
print(data)
li=list(range(10))
random.shuffle(li)
print(li)
quick_sort(li)
堆排序:
import random def sift(li, left, right): i = left j = 2 * i + 1 tmp = li[left] while j <= right: if j+1 <= right and li[j] < li[j+1]: j = j + 1 if tmp < li[j]: li[i] = li[j] i = j j = 2 * i + 1 else: break li[i] = tmp def heap_sort(li): n = len(li) for i in range(n//2-1, -1, -1): #建立堆 sift(li, i, n-1) for i in range(n-1, -1, -1): #挨个出数 li[0], li[i] = li[i],li[0] sift(li, 0, i-1) li=list(range(100000)) random.shuffle(li) print(li) heap_sort(li) print(li)
归并排序
假设现在的列表分两段有序,如何将其合成一个有序列表
这个过程称为一次归并
分解:将列表越分越小,直至分成一个元素
一个元素是有序的
合并:将两个有序列表归并,列表越来越大
代码:
1 import random 2 def merge(li, left, mid, right): 3 i = left 4 j = mid + 1 5 ltmp = [] 6 while i <= mid and j <= right: #左边右边都没排完 7 if li[i] < li[j]: 8 ltmp.append(li[i]) #升序排列 9 i += 1 10 else: 11 ltmp.append(li[j]) 12 j += 1 13 while i<= mid: #左边剩下了 14 ltmp.append(li[i]) #依次挨个追加 15 i += 1 16 while j <= right: 17 ltmp.append(li[j]) 18 j += 1 19 li[left:right+1] = ltmp 20 21 def _merge_sort(li,left,right): 22 if left < right: 23 mid = (left+right)//2 24 _merge_sort(li,left,mid) 25 _merge_sort(li,mid+1,right) 26 #print(li[left:right+1]) 27 merge(li,left,mid,right) 28 #print(li[left:right+1]) 29 30 @cal_time 31 def merge_sort(li): 32 _merge_sort(li, 0, len(li)-1) 33 34 li=list(range(100)) 35 random.shuffle(li) 36 print(li) 37 merge_sort(li) 38 print(li)
时间装饰器代码
import time def cal_time(func): def wrapper(*args, **kwargs): t1 = time.time() x = func(*args, **kwargs) t2 = time.time() print("%s running time %s secs."%(func.__name__, t2-t1)) return x return wrapper
一般情况下,就运行时间而言
快排 < 归并排序 < 堆排序
快排:极端情况下排序效率低
归并排序:需要额外的内存开销
堆排序:在快的排序算法中相对比较慢