NB 三人组
1.三人行
快排
堆排
归并
快排
思路:
#快速排序法 ''' 思路分析: 1.取一个元素p,使元素p归位。 2.列表被p分成两部分,左边都比p小,右边都比p大, 3.递归完成排序。 递归:第一个归位只是归为一位,所以需要递归把列表里的每一位数都归位了才能完成排序。 关键点: 1.归位 2.递归 partition函数里的逻辑: 1.拿去左边第一个值假如是5,做比较,现在第一个位置为空 2.从右边开始找比5小的数,放到那个空的位置。找到后移过去,自己的位置又位空, 3.从左边找,比5大的数,移过去空的位置,以此类推。 4.最后叠加,重合。 5 1 7 _ 1 7 1 _ 7 时间的复杂度: n*logn 最坏情况:n* 如:987654321 预防:随机找一个元素,就不找第一个元素,跟第一个元素对调一下。 '''
简单代码实现:
def partition(li,left,right): #无序列表,最小值,最大值 tmp =li[left] #拿去左边第一个值 while left < right: #左边小于右边,就一直循环 while left < right and li[right] >= tmp: right -= 1 li[left] = li[right] #把小于5的数,移到左边空的位置 while left < right and li[left] <= tmp: left += 1 li[right] = li[left] #把大于的5的数,移到右边空的位置 li[left] = tmp #最后还需要归位。 return left def _quick_sort(data,left,right): #data=列表,左边,右边 if left < right: #至少两个元素,才会递归 mid =partition(data,left,right) _quick_sort(data,left,mid-1) _quick_sort(data,mid+1,right) list = [2,3,4,1,5,6,8,9,7] _quick_sort(list,0,8) print(list)
和系统排序比较时间效率:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
import random import copy import sys import time sys.setrecursionlimit(100000) #更改最大递归深度 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): #无序列表,最小值,最大值 tmp =li[left] #拿去左边第一个值 while left < right: #左边小于右边,就一直循环 while left < right and li[right] >= tmp: right -= 1 li[left] = li[right] #把小于5的数,移到左边空的位置 while left < right and li[left] <= tmp: left += 1 li[right] = li[left] #把大于的5的数,移到右边空的位置 li[left] = tmp #最后还需要归位。 return left def _quick_sort(data,left,right): #data=列表,左边,右边 if left < right: #至少两个元素,才会递归 mid =partition(data,left,right) _quick_sort(data,left,mid-1) _quick_sort(data,mid+1,right) list = [2,3,4,1,5,6,8,9,7] _quick_sort(list,0,8) print(list) #加壳处理 @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) li1 = copy.deepcopy(li) li2 = copy.deepcopy(li) sys_sort(li1) #系统排序 _quick_sort(li) #快排排序
堆排
思路:
#堆排序 ''' 大根堆:一颗完全二叉树,任意节点都比其孩子节点大 小根堆:一颗完全二叉树,任意节点都比其孩子节点少 堆的性质: -向下调整性质 意思就是,左右子树都是堆,自身不是堆。 (划分身份: 省长,市长,村站,村民)若级别构不成省长,那么就会被下调,直到形成一个堆。 堆排序的过程: 1.建立堆 2.堆顶为最大元素 3.去掉堆顶,将堆最后一个元素放到堆顶,通过调整,让堆有序(让省长退休,找个傀儡,进行调整) 4.堆顶又有新值为:当前最大元素。 5.重复以上,完成排序。 详细讲解: 1.建立堆 一句话:农村包围城市,从叶子开始,从后往前调整。 (从村民到村长到市长到省长) 2.后面就是挨个出数的意思。 代码实现分析: 1.i指向父亲,j指向孩子。 '''
代码实现:
def sift(li,low,high): ''' :param li:列表 :param low: 堆根节点的位置 :param high:堆最后一个节点的位置 :return: 这是一个调整堆的过程 ''' i = low #父亲的位置 j = 2*i +1 #左孩子: 2*i +1 tmp = li[low] #存一下省长的位置。(纪委办) while j <= high: #只要有孩子就一直循环。 if j +1 <= high and li[j+1] > li[j]: #有右孩子存在的情况下:li[j]为左孩子,li[j+1]为右孩子,若右孩子大于左孩子。 j +=1 if tmp < li[j]: #原省长的级别比孩子的级别小。 li[i] = li[j] #把孩子向上调整1级 i = j j = 2*i +1 else: li[i] = tmp #若纪委办的原省长级别比孩子的级别大,复职对应的省份(干部)。 break else: li[i] =tmp #一撸到底,回归到村民 li =[2,9,7,8,5,0,1,6,4,3] sift(li,0,len(li)-1) print(li) 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): li[0],li[j] = li[j],li[0] #堆的大小少了一个元素(j-1) sift(li,0,j-1) heap_sort(li) print(li) # 打印如下: # [9, 8, 7, 6, 5, 0, 1, 2, 4, 3] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
归并
思路:
#归并排序法 ''' 根节点:头一个节点称为:'根节点' 叶子节点: 没有孩子节点的称为:'叶子节点' 树的深度: 从根开始往下走了几层就是: 树的深度 节点的度: 不算节点上面的叉,只算下面的叉。 树的度: 树包含的节点中,最大的度。 孩子节点: 如: A分出了B A为B的父节点 B为A的子节点 子树: 树里面包含的子树 归并排序分为: 1.一次归并: 把列表分为2段,这两段数组都是有序的,都有个指针, 把两段数组的指针比较大小,小的移到孤儿院,小的指针交给下一位挑战者。以此类推 2.归并是nb三人组里唯一不需要递归的。 '''
代码实现:
def merge(li,low,mid,high): ''' :param li: 列表 :param low: 开头的值 :param mid: 中间划分的值 :param high: 结尾的值 :return: ''' i =low #第1个有序的头值 j =mid+1 #第2个有序的头值 tmp=[] #孤儿院 while i <= mid and j <= high: if li[i]<li[j]: tmp.append(li[i]) i +=1 else: tmp.append(li[j]) j +=1 while i <=mid: tmp.append(li[i]) i +=1 while j <=high: tmp.append(li[j]) j +=1 li[low:high+1] = tmp # print(li[low:high+1]) #递归 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) #然后merge # print(li[low:high + 1]) def merge_sort(li): return _merge_sort(li,0,len(li)-1) import random li = list(range(10)) random.shuffle(li) print(li) merge_sort(li) print(li)