18年春季第四题 PAT甲级 1147 Heaps (30分) 可以不建树

这篇博客介绍了如何判断一个完全二叉树是否为堆,包括最大堆和最小堆,并提供了相关知识点和解题思路。内容涉及堆的定义、层序遍历和后序遍历,以及如何通过深度优先搜索实现后序遍历序列的生成。同时,博主分享了PAT甲级考试中关于堆的题型特点和备考建议。

汇总贴

2020年3月PAT甲级满分必备刷题技巧

题目

来源:https://pintia.cn/problem-sets/994805342720868352/problems/994805342821531648

In computer science, a heap is a specialized tree-based data structure that satisfies the heap property: if P is a parent node of C, then the key (the value) of P is either greater than or equal to (in a max heap) or less than or equal to (in a min heap) the key of C. A common implementation of a heap is the binary heap, in which the tree is a complete binary tree. (Quoted from Wikipedia at https://en.wikipedia.org/wiki/Heap_(data_structure))

Your job is to tell if a given complete binary tree is a heap.

Input Specification:

你提出了一个非常关键的问。我们来看这段代码: ```cpp template<class Data> class PersistentLeftistTree { public: PersistentLeftistTree() { tr.emplace_back(); } int add_node(Data val) { tr.push_back(Node{0, 0, 0, val}); return tr.size() - 1; } int merge(int x, int y) { if (!x || !y) return x + y; if (tr[x].val > tr[y].val) swap(x, y); tr.push_back(tr[x]); int z = tr.size() - 1; tr[z] = merge(tr[x].rc, y); if (tr[tr[z].lc].dis < tr[tr[z].rc].dis) swap(tr[z].lc, tr[z].rc); tr[z].dis = tr[tr[z].rc].dis + 1; return z; } public: struct Node { int lc, rc, dis; Data val; }; vector<Data> tr; }; ``` ### 问析: 你问的是:**为什么 `heaps.tr` 是私有成员?它是声明在 `public` 中了吗?** 答案是:**`tr` 并是类的 `public` 成员变量**,虽然它在代码中看起来像是写在 `public:` 标签之后,但实际上: - **`public:` 标签的作用域是从它出现的位置开始,直到下一个访问修饰符(如 `private:`、`protected:`)或类结束为止**。 - 在你的代码中,`struct Node { ... };` 是在第一个 `public:` 区块中定义的。 - 然后你又写了一个 `public:` 标签,**接着定义了 `vector<Data> tr;`**。 所以 **`tr` 是 `public` 的成员变量**,也就是说在类外部是可以通过对象访问 `tr` 的。 --- ### 那为什么 `heaps.tr` 会出错? 你可能误解了 `tr` 的类型。 你定义的是: ```cpp vector<Data> tr; ``` 但你访问的是: ```cpp heaps.tr[rt].val ``` 注意!**`tr[rt]` 是一个 `Data` 类型的值**(在这里是 `double`),而是 `Node` 类型! 但是你在类里面还定义了一个结构体: ```cpp struct Node { int lc, rc, dis; Data val; }; ``` 这说明你本意可能是让 `tr` 是一个 `vector<Node>`,用来存储节点信息,包括 `lc`、`rc`、`val` 等字段。 但你却写成了: ```cpp vector<Data> tr; ``` 也就是一个 `vector<double>`(因为 `Data` 是模板参数,而你在主函数中实例化为 `PersistentLeftistTree<double>`)。 --- ### 总结错误原因: 1. **`tr` 是 public 的,访问权限没有问。** 2. **`tr` 的类型是 `vector<double>`,是你期望的 `vector<Node>`。** 3. 所以你写的 `heaps.tr[rt].val` 是错误的,因为 `heaps.tr[rt]` 是一个 `double`,**没有 `.val` 成员**。 4. 同理,你也无法访问 `.lc`、`.rc` 等字段。 --- ### 正确做法: 将 `tr` 的类型改为 `vector<Node>`: ```cpp vector<Node> tr; ``` 这样,`tr[rt]` 就是一个 `Node` 对象,就可以访问 `.val`、`.lc`、`.rc` 等字段。 --- ### 修改建议: 将类中这一行: ```cpp vector<Data> tr; ``` 改为: ```cpp vector<Node> tr; ``` 然后你就可以在 `main()` 中安全访问: ```cpp heaps.tr[rt].val ``` --- ### 总结: - `tr` 是 public 的,问在访问权限。 - 错误是由于你访问了 `double` 类型的 `.val` 字段,而 `double` 没有 `.val`。 - 实际上你应该是想访问 `Node` 类型的 `.val`,所以需要将 `tr` 改为 `vector<Node>`。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值