原题目: 1155 Heap Paths (30 分).
题意
给出一棵完全二叉树的层序遍历序列(无重复数值),
① 打印出所有叶子节点到根节点的路径,并且按从右到左的顺序;
② 最后,判断是否是heap,是max(父结点不小于孩子)还是min(父结点不大于孩子)。
分析
- 将题给序列存在数组中,则可以通过下标访问结点及其孩子结点、父结点。
- 打印路径:① 用DFS递归实现先序(根右左)遍历;② 需要额外的数组 存储push_back() 并 维护pop_back() 路径。
- 判断heap:从数组的2号元素开始,依次与其父结点 i/2 比较大小。
知识点
- 用数组存储完全二叉树——下标亲戚关系、层序遍历序列、叶结点与空结点判断(常作递归边界)。👉 传送门:堆(Heap):完全二叉树(Complete Binary Tree)⭐⭐⭐【常忘用】
- DFS之先序遍历——递归必备:递归边界+递归式。
- vector的应用——用push_back()与pop_back()实现路径维护(类似栈,但是vector数组可以随机访问)。
词汇
WORDS & CHUNKS | 释义 | WORDS & CHUNKS | 释义 |
---|---|---|---|
path | 路径 | implementation | 实现,实施 |
the level order traversal sequence | 层序遍历序列 | property | 性质 |
in non-increasing/non-decreasing order | 非递增/非递减 | DFS(Depth-First-Search) | 深度优先搜索 |
CODE
#include <iostream>
#include <vector>
using namespace std;
int n;
vector<int> v, pre; //层序遍历序列(从1号开始),先序遍历路径(从0号开始)
void DFS(int index); //输出路径
int main()
{
cin >> n;
v.resize(n+1);
for ( int i=1; i<=n; i++ )
cin >> v[i]; //完全二叉树的层序遍历序列与数组顺序相同
//DFS递归遍历
DFS(1);
//判断heap
int isMin = 1, isMax = 1; //1代表”是Min/Max heap
for (int i=2; i<=n; i++ ){ //每个结点i与其父结点i/2比较
if ( v[i]>v[i/2] ) isMax = 0;
else if ( v[i]<v[i/2] ) isMin = 0;
if ( !isMin && !isMax ) break; //Not Heap时提前结束循环
}
if ( isMin || isMax ){
printf("%s Heap", isMin==1 ? "Min" : "Max" );
}
else
cout << "Not Heap";
return 0;
}
void DFS(int index){ //用数组下标来直接访问
if ( index>n ) return;
if ( index*2>n && index<=n ){ //递归边界:叶子结点 → 输出路径
pre.push_back(v[index]); //叶子结点也需压入
for ( int i=0; i<pre.size(); i++ )
printf("%d%s",pre[i], i==pre.size()-1 ? "\n" : " ");
return;
}
//访问根结点
pre.push_back(v[index]);
//优先遍历右子树
if ( index*2+1<=n ){ //若有右孩子
DFS(index*2+1);
pre.pop_back();
}
DFS(index*2);
pre.pop_back();
}