堆排序中 i 位置的节点的子节点位置为 2i+1, 2i+2, 父节点为 (i-1) / 2

在堆排序中使用到了左右子节点,它们的节点位置是 2i + 1 和 2i + 2,下面是如何得到这个结论:

1.我们首先假设一个节点:它的数组下标是 i ,在二叉树的第 n 层的第 x + 1 个
在这里插入图片描述
我们可以知道完全二叉树的前 n 层的总结点数是 2 ^ n - 1 个,在第n层的节点,前n-1层有 2^(n-1) - 1 个节点,加上他本层前面的x个节点,则:

 i = 2^(n-1) - 1 + x

2.我们再来看子节点,i 的子节点在第 n + 1 层,对于左子节点,令他在数组中下标为 j。
左子节点在n+1层中,前面应该有2x个节点,(因为i在第n层前面有x个,每一个节点在下一层都会有2个节点)。
在这里插入图片描述

所以得到

j = (2^n - 1) + 2x = 2(2^(n-1) + x -1) + 1 = 2i + 1

这样左节点下标 j = 2i+1,右节点也就是 2i+2。

3.再来分析父节点为什么是 (i - 1) / 2

i 的父节点在第 n - 1 层,对于父节点,令他在数组中下标为 k。
在这里插入图片描述
因为 i = 2^(n-1) - 1 + x
得到 i + 1 = 2^(n-1) + x

k = 2^(n-2) - 1 + x/2 
  = 2^(n-1)/2 + x/2 -1 
  = (2^(n-1) + x)/2 -1
  = (i-1)/2
### 堆排序中首个 `for` 循环变量 `i` 的功能与意义 在堆排序算法中,首个 `for` 循环的主要目的是构建初始的最大堆(对于升序排列)。具体来说,该循环的作用是对输入数组中的每一个可能成为子节点的元素调用调整函数(通常称为 `heapify`),从而确保整个数组满足最大堆性质。 #### 变量 `i` 的含义 变量 `i` 表示当前正在处理的节点索引。由于堆是一种完全二叉结构,在数组表示形式下,父节点与其子节点之间的关系可以通过简单的计算得出: - 左孩子节点索引为:`2 * i + 1` - 右孩子节点索引为:`2 * i + 2` 因此,当从最后一个非叶子节点开始向上遍历时,可以逐步将每个子调整成最大堆[^3]。 #### 初始位置的选择 首次进入外层 `for` 循环时,`i` 被初始化为 `(length / 2) - 1`,这是因为在基于零索引的数组实现中,`(length / 2)` 是第一个叶子节点位置,而其前一个元素即为最后一个非叶子节点[(length/2)-1]。这样设置能够保证只对那些具有至少一个孩子的内部节点执行必要的操作。 #### 功能描述 随着每次迭代减少一次单位值(`--i`),程序依次访问更靠近顶部的层次上的结点直到到达顶端(root),期间不断应用下沉逻辑来维持整体结构作为有效的大顶堆状态。最终完成初步构造过程之后, 接下来的步骤就是交换首尾元素并缩小考虑范围再重复上述动作直至全部序列有序化结束[^2]。 ```java public class HeapSort { public static void heapSort(int[] array){ int n = array.length; // Build max heap. for (int i = n / 2 - 1; i >= 0; i--) { heapify(array, n, i); } // Extract elements one by one from the heap. for (int i=n-1; i>=0; i--){ swap(array, 0, i); heapify(array, i, 0); } } private static void heapify(int[] arr,int N ,int i ){ ... } private static void swap(int []a ,int x ,int y){...} } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值