堆排序
树
| 树是一种数据结构 比如:目录结构 |
| 树是一种可以递归定义的数据结构 |
| 树是由n个节点组成的集合: |
| 如果n=0,那这是一颗空树 |
| 如果n>0,那存在1个节点作为数的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树 |
| |
一些概念:
| 根节点、叶子节点 |
| 数的深度(高度) |
| 树的度 |
| 孩子节点/父节点 |
| 子树 |
二叉树:
| 度不超过2的树 |
| 每个节点最多有两个孩子节点 |
| 两个孩子节点被区分为左孩子节点和右孩子节点 |
满二叉树:
| 一个二叉树,如果每一个层的节点数都达到最大值,则这个二叉树就是满二叉树 |
| 完全二叉树: |
| 叶节点只能出现在最下层和次下层,并且最下面一层的节点都集中在该层最左边的若干位置的二叉树 |
二叉树的存储方式(表示方式)

| 链式存储方式 |
| 顺序存储方式 |
| |
| 父节点和左孩子节点的编号小标有什么关系: |
| i->2i+1 |
| 父节点和右孩子节点的编号下表有什么关系: |
| i->2i+2 |
堆排序——什么是堆
| 堆:一种特殊的完全二叉树结构 |
| 大根堆:一棵完全二叉树,满足任一节点都比其孩子节点大 |
| 小根堆:一棵完全二叉树,满足任一节点都比其孩子节点小 |
堆排序过程
| 1、建立堆 |
| 2、得到堆顶元素,为最大元素 |
| 3、去掉堆顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序 |
| 4、堆顶元素为第二大元素 |
| 5、重复步骤3,直到堆变空 |
堆排序——堆的向下调整性质
| 假设根节点的左右子树都是堆,但根节点不满足堆的性质 |
| 可以通过一次向下的调整来将其变成一个堆 |




向下调整代码:
| def sift(li,low,high): |
| ''' |
| :param li:列表 |
| :param low:堆的根节点位置 |
| :param high:堆的最后一个元素的位置 |
| :return: |
| ''' |
| i=low |
| j=2*i+1 |
| tmp=li[low] |
| while j<=high: |
| if j+1<=high and li[j+1]>li[j]: |
| j=j+1 |
| if li[j]>tmp: |
| li[i]=li[j] |
| i=j |
| j=2*i+1 |
| else: |
| li[i]=tmp |
| break |
| else: |
| li[i]=tmp |
排序代码:
| def heap_sort(li): |
| n=len(li) |
| for i in range((n-2)//2,-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=[i for i in range(100)] |
| import random |
| random.shuffle(li) |
| print(li) |
| heap_sort(li) |
| print(li) |
堆排序————内置模块
| python内置模块——heapq |
| 常用函数: |
| heapify(x) |
| heappush(heap,item) |
| heappop(heap) |
代码:
| import heapq |
| import random |
| |
| li=list(range(100)) |
| random.shuffle(li) |
| print(li) |
| heapq.heapify(li)建堆 |
| n=len(li) |
| for i in range(n): |
| print(heapq.heappop(li),end=',') |
堆排序——topk问题
| 现在有n个数,设计算法得到前k大的数。(k<n) |
| 解决思路: |
| 排序后切片 o(nlogn) |
| 排序LowB三人组 o(mn) |
| 堆排序思路 o(mlogn) |
| |
| 解决思路: |
| 取列表前k个元素建一个小根堆。堆顶就是目前第k大的数 |
| 依次向后遍历列表,对于列表中的元素,如果小于堆顶,则忽略该元素;如果大于堆顶,则将堆顶更换为该元素,并且对堆进行一次调整; |
| 遍历列表所有元素后,倒序弹出堆顶 |
代码:
| def topk(li,k): |
| heap=li[0:k] |
| for i in range((k-2)//2,-1,-1): |
| sift(heap,i,k-1) |
| #1、建堆 |
| for i in range(k,len(li)-1): |
| if li[i]>heap[0]: |
| heap[0]=li[i] |
| sift(heap,0,k-1) |
| |
| #2、遍历 |
| for i in range(k-1,-1,-1): |
| heap[0],heap[i]=heap[i],heap[0] |
| sift(heap,0,i-1) |
| |
| #3、出数 |
| return heap |
| import random |
| li=list(range(1000)) |
| random.shuffle(li) |
| print(topk(li,10)) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义