最大堆/最小堆

堆有最大堆和最小堆之分。它们在表现形式上都是一棵完全二叉树,在存储时按层次遍历的方式存储。

最大堆就是每个节点的值都>=其左右孩子(如果有的话)值的完全二叉树。

最小堆便是每个节点的值都<=其左右孩子值的完全二叉树。 


设有n个元素的序列{k1,k2,...,kn},当且仅当满足下列关系时,称之为堆。 
 

堆的三种基本操作(以下以最大堆为例): 

⑴最大堆的插入

由于需要维持完全二叉树的形态,需要先将要插入的结点x放在最底层的最右边,插入后满 足完全二叉树的特点; 
  然后把x依次向上调整到合适位置满足堆的性质,例如下图中插入80,先将80放在最后,然后两次上浮到合适位置. 
  时间:O(logn)。  “结点上浮” 

⑵删除 
   操作原理是:当删除节点的数值时,原来的位置就会出现一个孔,填充这个孔的方法就是, 
把最后的叶子的值赋给该孔并下调到合适位置,最后把该叶子删除。 
  
如图中要删除72,先用堆中最后一个元素来35替换72,再将35下沉到合适位置,最后将叶子节点删除。 
 “结点下沉” 

 

⑶初始化 
方法1:插入法: 
  从空堆开始,依次插入每一个结点,直到所有的结点全部插入到堆为止。 
  时间:O(n*log(n)) 
  方法2:调整法: 
    序列对应一个完全二叉树;从最后一个分支结点(n div 2)开始,到根(1)为止,依次对每个分支结点进行调整(下沉)
以便形成以每个分支结点为根的堆,当最后对树根结点进行调整后,整个树就变成了一个堆。 
  时间:O(n) 
对如图的序列,要使其成为堆,我们从最后一个分支结点(10/2),其值为72开始,依次对每个分支节点53,18,36 45进行调整(下沉). 
 
 
 

1,8,6,2,5,4,7,3调整为小根堆的过程:



<think>好的,我现在需要帮助用户了解如何将转换为最大堆最小,并提供相应的算法和代码示例。首先,我得回忆一下的基本结构和调整方法。根据引用中的内容,建有向上调整和向下调整两种方法,这可能和用户的问题相关。 用户提到的引用[1]里提到了向上调整建和向下调整建,所以这两种方法应该是关键。最大堆最小的区别在于父节点与子节点的大小关系,最大堆的父节点大于等于子节点,最小则相反。所以,调整结构的时候需要根据目标类型来比较节点的大小,并交换位置。 接下来,我需要整理调整的步骤。对于构建最大堆,通常使用向下调整的方法,也就是从最后一个非叶子节点开始,逐个调整每个子树为最大堆。而向上调整可能是在插入元素时使用,从插入的位置向上调整。不过用户的问题是关于如何转换整个,所以可能需要先构建结构,然后进行调整。 然后,我需要考虑代码实现。根据引用中的示例,Python可能是一个合适的语言。代码需要包括向下调整的函数,以及构建最大堆最小的过程。比如,对于最大堆的构建,从中间节点开始向前遍历,对每个节点执行向下调整。同样的,最小的构建逻辑类似,但比较的方向相反。 还要注意用户提供的引用[3]提到优化排序的方法,比如减少比较次数,这可能影响到调整时的具体实现细节,但用户的问题更关注基础实现,所以可能需要先给出基本方法,再提到可能的优化点。 另外,用户可能需要了解两种调整方法的应用场景。例如,向上调整适用于插入新元素后调整,而向下调整适用于构建初始或者删除元素后的调整。这些信息是否需要包含在回答中呢?根据用户的问题,他们想了解如何转换结构,所以应该重点放在构建最大/最小的方法上,而不是具体操作的应用场景,但可以简要提及。 现在,我需要确保代码示例正确。例如,向下调整的函数需要接收数组、当前节点索引、的大小以及比较的方向(最大堆还是最小)。在构建时,从最后一个非叶子节点开始,向前遍历到根节点,逐个调整。这个过程对于最大堆最小都是适用的,只是比较条件不同。 可能还需要考虑如何通过一个函数来支持两种类型,例如通过传入一个比较函数或者标志位来决定是大还是小。这样代码会更简洁,避免重复。例如,在向下调整时,根据是最大堆还是最小来决定是寻找最大子节点还是最小子节点。 最后,总结步骤:确定类型(最大或最小),从非叶子节点开始调整,使用向下调整方法,确保每个子树满足的性质。代码示例需要展示这个过程,并给出测试用例,比如将一个无序数组转换为最大堆最小。 检查是否有遗漏的部分,比如时间复杂度或者优化方法,但用户主要问的是方法和代码示例,所以这些可能作为补充内容,但不需要深入。同时,确保引用的正确引用,例如引用[1]提到向上调整和向下调整,引用[3]提到优化方法,可以在适当的地方引用。</think>### 如何构建最大堆最小的构建核心在于调整父子节点的关系,使其满足最大堆(父节点值 ≥ 子节点)或最小(父节点值 ≤ 子节点)的性质。关键是通过**向下调整**(Heapify Down)或**向上调整**(Heapify Up)方法实现[^1]。 --- ### 一、算法步骤 #### 1. **向下调整法(以构建最大堆为例)** - **步骤1**:从最后一个非叶子节点开始,向前遍历到根节点。 - **步骤2**:对每个节点,比较其与左右子节点的值。 - **步骤3**:若子节点值更大,则交换父节点与最大子节点的位置。 - **步骤4**:递归调整交换后的子树,直到满足性质。 #### 2. **向上调整法(插入元素时使用)** - **步骤1**:将新元素插入末尾。 - **步骤2**:比较新元素与其父节点的值。 - **步骤3**:若新元素更大(最大堆)或更小(最小),则交换位置。 - **步骤4**:重复步骤2-3,直到满足性质。 --- ### 二、代码实现(Python) #### 1. **向下调整函数(支持最大堆/最小)** ```python def heapify(arr, n, i, is_max_heap=True): target = i left = 2 * i + 1 right = 2 * i + 2 # 根据类型选择比较条件 compare = (lambda a, b: a > b) if is_max_heap else (lambda a, b: a < b) if left < n and compare(arr[left], arr[target]): target = left if right < n and compare(arr[right], arr[target]): target = right if target != i: arr[i], arr[target] = arr[target], arr[i] heapify(arr, n, target, is_max_heap) ``` #### 2. **构建最大堆/最小** ```python def build_heap(arr, is_max_heap=True): n = len(arr) # 从最后一个非叶子节点开始调整 for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i, is_max_heap) return arr # 示例 arr = [3, 5, 1, 4, 2] max_heap = build_heap(arr.copy(), is_max_heap=True) # 输出: [5,4,1,3,2] min_heap = build_heap(arr.copy(), is_max_heap=False) # 输出: [1,2,3,4,5] ``` --- ### 三、关键分析 1. **时间复杂度**:构建的时间复杂度为 $O(n)$,向下调整单次操作为 $O(\log n)$[^3]。 2. **应用场景**: - 最大堆常用于优先队列(如任务调度)。 - 最小适用于需要快速获取最小值的场景(如Dijkstra算法)[^2]。 3. **优化**:可通过减少比较次数或混合排序(如小数组用插入排序)提升性能[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值