关于堆的一点总结

完全二叉树与堆

一、什么是堆

堆是一颗被完全填满的二叉树,可能的例外是在底层,底层上的元素从左到右填入,这样的树被称为完全二叉树。


二、堆的特性

1、如果一个堆有N个节点,那么堆的高度为 h = [lgN] 。即N 在 2到 2h+1-1  之间。

2、父节点的值大于(大顶堆)或小于(小顶堆)子节点的值。


三、堆支持的操作

1、上浮 shiftup
2、下沉 shiftdown
3、插入 push
4、弹出 pop
5、取顶 top

其中,当前元素若可能与下一层元素交换,就是siftdown;若可能与上一层元素交换,就是siftup。或者说当前元素被“挖出”后形成的“坑”,若往上升就是siftup,若往下降就是siftdown。当你插入了某个节点或弹出了节点时,为了恢复堆的性质,就可能要执行这两种操作。


四、堆的表示

堆可以用数组来表示。若从下标0开始存放元素的话,那么对于数组任一位置 i上的元素,其左儿子在位置2i+1上,右儿子在2i+2上,它的父亲则在[(i-1)/2]上。

对于一个数组a,可以通过这种方式把它转换为堆:就是对下标为[a.length/2]-1一直到0为止 的位置(实际上也就是成为父节点的位置)执行上面所说的“下沉” 操作。


参考:

1、http://www.cnblogs.com/JVxie/p/4859889.html

2、http://blog.youkuaiyun.com/ditian1027/article/details/19987239

3、http://blog.youkuaiyun.com/zhutulang/article/details/7746033

<think>好的,我现在需要解决用户的问题,关于如何用Java实现的数据结构以及相关判断,特别是针对PTA题目L2-012的要求。首先,我需要回忆的基本概念和操作。通常是一个完全二叉树,分为最小和最大。在这个题目中,用户提到的是最小,所以每个父节点的值都要小于或等于其子节点的值。 首先,用户需要实现的数据结构。Java中可以用数组来模拟结构,因为完全二叉树可以按层序存储在数组中。对于索引i的节点,其左子节点在2i+1,右子节点在2i+2,父节点在(i-1)/2的位置。插入元素时,通常采用上浮(siftUp)操作,将新元素添加到数组末尾,然后向上调整直到满足的性质。 接下来是处理输入的n个元素,构建最小。需要注意的是,题目中的是逐个插入元素构建的,而不是通过数组调整构建的。因此,不能直接将数组化,而是需要逐个插入,每次插入后调整的结构,保证每次插入后都是有效的最小。这一点很关键,因为不同的构建方式会影响节点的父子关系。 然后是处理m个命题判断。命题类型包括:判断某个节点是否是根节点,是否是兄弟节点,是否是父子关系,是否是子节点。需要针对每种情况编写判断逻辑。 对于根节点的判断,只需要检查该节点的索引是否为0即可。兄弟节点需要两个节点的父节点相同,且不是同一个节点。判断父子关系时,需要确认其中一个节点是否是另一个节点的父节点,即通过索引关系计算。子节点的判断则是父节点关系的反向,检查是否存在父节点。 在实现过程中,可能需要一个哈希表来存储每个值对应的索引,这样可以快速查找节点在中的位置。因为题目保证所有命题中的节点值都存在,所以哈希表不会出现键不存在的情况。 现在考虑代码结构。首先读取n和m,然后读取n个元素,逐个插入构建。插入时维护数组和哈希表。然后处理每个命题字符串,解析出相应的节点和关系,调用对应的判断方法返回结果。 在处理字符串解析时,需要注意不同的命题格式,例如“24 is the root”只需要提取值24,判断其索引是否为0。“26 and 23 are siblings”需要提取两个值,并检查它们的父节点是否相同。而“46 is the parent of 23”则需要检查23的父节点是否是46。同样,“23 is a child of 10”需要检查23的父节点是否是10。 可能遇到的难点是字符串的解析,尤其是如何正确提取出数值和判断类型。可以使用字符串的split方法,根据关键词如“root”, “siblings”, “parent”, “child”来分割处理。 此外,需要注意的构建是否正确,特别是在逐个插入元素时,上浮操作的实现是否正确。每个新元素插入后,需要和父节点比较,如果更小则交换位置,直到根节点或父节点更小为止。 测试时,可以检查示例输入是否得到正确的输出。例如示例输入中的五个元素46、23、26、24、10,构建后的数组应该是[10,23,26,46,24]。这样,24的索引是3,其父节点是(3-1)/2=1,即23。所以命题“24 is the root”是错误的,返回F。而26和23的父节点都是0(10),所以他们是兄弟节点,返回T。46是23的父节点吗?23的索引是1,父节点是0(10),所以46不是父节点,返回F。而23的父节点是10,所以“23 is a child of 10”是正确的,返回T。 总结步骤:构建结构,正确维护索引映射,解析命题,编写判断逻辑。需要确保每个步骤都正确无误,特别是的构建和索引计算部分。</think>### Java实现最小结构及判断方法 #### 1. 结构实现 最小使用数组存储,关键操作包括插入元素和维护性质: ```java class MinHeap { private List<Integer> heap = new ArrayList<>(); private Map<Integer, Integer> indexMap = new HashMap<>(); // 插入元素 public void insert(int val) { heap.add(val); siftUp(heap.size() - 1); } // 上浮操作 private void siftUp(int idx) { while (idx > 0) { int parent = (idx - 1) / 2; if (heap.get(idx) >= heap.get(parent)) break; Collections.swap(heap, idx, parent); indexMap.put(heap.get(idx), idx); indexMap.put(heap.get(parent), parent); idx = parent; } indexMap.put(heap.get(idx), idx); } } ``` #### 2. 命题判断方法 建立索引映射表辅助快速查询: ```java boolean isRoot(int x) { return indexMap.get(x) == 0; } boolean areSiblings(int x, int y) { int idxX = indexMap.get(x); int idxY = indexMap.get(y); if (idxX == idxY) return false; return (idxX - 1) / 2 == (idxY - 1) / 2; } boolean isParent(int parent, int child) { int childIdx = indexMap.get(child); int parentIdx = (childIdx - 1) / 2; return parentIdx >= 0 && heap.get(parentIdx) == parent; } ``` #### 3. 输入处理流程 ```java public static void main(String[] args) { MinHeap heap = new MinHeap(); Scanner sc = new Scanner(System.in); int n = sc.nextInt(), m = sc.nextInt(); for (int i = 0; i < n; i++) { heap.insert(sc.nextInt()); } sc.nextLine(); while (m-- > 0) { String s = sc.nextLine(); // 解析逻辑(示例) if (s.contains("root")) { int val = Integer.parseInt(s.split(" ")[0]); System.out.println(heap.isRoot(val) ? "T" : "F"); } // 其他命题解析类似 } } ``` #### 4. 关键特性说明 - 时间复杂度:插入操作$O(\log n)$,查询操作$O(1)$ - 空间复杂度:$O(n)$ - 索引映射表维护元素位置,实现快速查询[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值