三种NB的排序
主要内容:
- 1.快速排序
- 2.堆牌
- 3.归并排序
1. 快速排序
- 取一个元素p(第一个元素),使元素p归位;
- 列表被p分成两部分,左边都比p小,右边都比p大;
- 递归完成排序
1.1 快排代码书写
import random from cal_time import cal_time def _quick_sort(lst,left,right): if left < right: mid = partition(lst,left,right) _quick_sort(lst,left,mid-1) _quick_sort(lst,mid+1,right) def partition(lst,left,right): tmp = lst[left] while left < right: while left < right and lst[right] >= tmp: right -=1 #当这个while循环退出时,将右边比tmp大的数放到左边 lst[left] = lst[right] #此时进入下边的while循环,从左边选出比tmp大的数去田右边刚留出的空 while left < right and lst[left] <= tmp: left +=1 #循环退出时候,将比tmp大的数放到右边 lst[right] = lst[left] #循环退出 lst[left] = tmp return left @cal_time def quick_sort(li): _quick_sort(li, 0, len(li)-1) li = list(range(10000)) random.shuffle(li) quick_sort(li) #quick_sort running time: 0.021941661834716797 secs.
1.2 快排的时间复杂度 O(nlogn)
- 递归深度并不是很大 , 因为他是分层的,每次大概少一半
1.3 快排的问题
- 最坏情况: 当所有的数是倒序 ,此时不是logn层,每次递归只让元素少一个,时间复杂度编程 O(n^2) (可以通过修改partition函数进行解决)
def partition(li, left, right): i = random.randint(left, right) li[i], li[left] = li[left], li[i] 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
- 递归
1.4 另一种partition的写法
#将最后一个元素归为 def partition2(li, left, right): # 区域1:[left, i] 区域2:[i+1, j-1] i = left - 1 # 初识区域1和区域2都空 left = i此时就时有值的所以只能-1 for j in range(left, right): if li[j] < li[right]: # 归到区域1 i += 1 li[j], li[i] = li[i], li[j] li[right], li[i+1] = li[i+1], li[right] return i+1