堆排序,向上调整,向下调整,前K个问题

您所在的位置:网站首页 向上调节向下调节名词解释是什么 堆排序,向上调整,向下调整,前K个问题

堆排序,向上调整,向下调整,前K个问题

2024-07-16 04:21| 来源: 网络整理| 查看: 265

堆排序,向上调整,向下调整,前K个问题 堆排序 1. 什么是堆?2. 堆的存储 2.1 根节点存储堆2.2 使用数组法存储堆 3. 堆的调整 3.1 堆的调整方法(以小顶堆为例) (1)自顶向下(2)自底向上 4. 堆的构建和删除节点 4.1 插入节点进堆4.2 构建堆4.3 删除堆的节点 5. 堆排序6. 前k个问题本文的代码链接 1. 什么是堆?

堆就是一棵完全二叉树,分为大顶堆和小顶堆

大顶堆:每一个父节点都比其子节点大,故根节点为最大 7 / \ 6 5 / \ / \ 4 3 2 1 小顶堆:每一个父节点都比其子节点小,故根节点为最小 1 / \ 2 3 / \ / \ 4 5 6 7

注意,这里说的是只是与当前节点得父节点比较,因此比如以下这个,也是小顶堆

1 / \ 100 3 / \ / \ 101 1005 6 700 2. 堆的存储 2.1 根节点存储堆

由于堆其实就是一棵完全二叉树,因此我们可以用树的存储的方式,节点类:

class HeapNode(object): def __init__(self): self.val = 0 self.left_child = None self.right_child = None

使用根节点存储堆,需要记录最后一个节点,合适进行不断拓展和不断调整的堆

2.2 使用数组法存储堆

使用数组存储堆,这是我们一般使用的方法,这种方法一般是在堆排序中进行使用,其好处是方便定位到相关的节点位置,对于上述小顶堆,存储格式为:

min_heap = [1, 2, 3, 4, 5, 6, 7]

其中:

第0个结点左右子结点下标分别为1和2第i节点父结点下标:(i–1)/2第i节点左孩子下标:2∗i+1第i节点右孩子下标:2∗i+2

本文主要是使用数组存储堆的方式

3. 堆的调整

对于堆的调整,涉及到三个问题:

调整堆,插入堆之后,对插入的节点使用调整算法进行调整。堆的调整算法,分为两个: 自顶向下:主要用于堆删除节点,删除结点之后把最后一个节点替换到,当前根节点位置,对此节点进行自顶向下操作自底向上:主要用于节点的插入,当一个节点插入到这个堆之后,向上调整堆,堆还能符合大顶堆或者小顶堆的定义。 插入堆,把需要插入的节点放在堆的最后一个节点之后的位置,对当前插入的这个节点进行自底向上的调整删除堆的节点,删除堆节点的操作,只能够删除根节点,把根节点和最后一个节点交换位置之后,然后弹出最后一个节点,并且对当前堆进行自顶向下的操作 3.1 堆的调整方法(以小顶堆为例) (1)自顶向下

自顶向下调整堆流程:

从第一个节点,即i=0节点开始,记节点为parent,记当前下标为index。

找到其左右children中的最小值,记为min。

比较 parent 和 min 的值,如果 min < parent ,则交换min和data[index],并且把index移动到min的下标,继续向下比较。

当出现data[index] 没有比 parent 小的子节点,或者没有子节点(即计算出的子节点下标比data_len大),此时需要交换最后一次,即把parent位置的数据,与当前index指向的数据交换,结束循环

处理完当前节点之后,从parent的下一个节点出发,重复上述流程,一直遍历完每一个节点。

def min_adjust_heap_top2down(data, index): """ 调整堆,自顶向下,用于堆化数组 :param data: List[int] :param index: 调整第几个节点,一般是从第0个节点开始 :return: """ if not data: return data_len = len(data) node = data[index] left_child = 2 * index + 1 right_child = 2 * index + 2 while left_child node: break # 交换父子节点 data[index], data[min_child] = data[min_child], data[index] # index指向当前min,继续对子节点进行比较 index = min_child left_child = 2 * index + 1 right_child = 2 * index + 2 # 与比较到最后一个节点进行交换 data[index] = node (2)自底向上

自底向上调整堆,则相对的要比较简单一些,一般用于堆的插入,只要不断的和父节点比较即可,步骤如下:

从最后一个节点开始,记为children计算此节点的父节点(父节点下标:(i-1)/2),下标记为 index,如果 children < data[index],则把此处的节点与children交换,然后使 index指向它的父节点,继续向上比较当得到 parent < data[index],或者没有父节点了(即计算出来的父节点的值= 0: # 如果父节点比当前节点小,则直接返回了 if data[parent]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3