PAT甲级1155Heap Paths

题目链接

https://pintia.cn/problem-sets/994805342720868352/problems/1071785408849047552

题解

题目要求

堆(大顶堆或小顶堆)中,任意一条从根结点到叶子结点的路径上的值一定是非递增序列或者非递减序列。

现在给定一个完全二叉树,请检查它的每一条路径,判断这棵树是不是堆。

  • 输入

    • N:正整数,大于1,不超过1000,树中结点的数量
    • N个结点的值(互异):都是int范围内,按照层次遍历的顺序给出
  • 输出

    对于每棵树

    1. 先输出所有从根结点到叶子结点的路径,每条路径占一行,数字间用一个空格间隔,首尾不能有多余空格

      输出顺序:对于每个结点,其右子树的所有路径要先于其左子树的所有路径输出

    2. 输出这颗树是大顶堆还是小顶堆,或者它不是堆

思路

  1. 利用完全二叉树的性质,将结点记录到一维数组中
  2. 使用DFS,使用vecotr记录当前遍历到的所有结点(即路径),如果当前结点是叶子结点则输出这条路径,否则先遍历右子树再遍历左子树
  3. 在DFS过程中判断是否违背大小顶堆性质
  4. 最后输出该树是否是大小顶堆

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Problem: PAT Advanced 1155
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/1071785408849047552
// Tags: Tree DFS Heap

#include <iostream>
#include <vector>
using namespace std;

int n;
bool isMaxHeap = true, isMinHeap = true;
int nodes[2010]; // 索引为[1,n]的元素有效
vector<int> path; // 目前遍历到的所有结点

void dfs(int i){
if (i > n) return; // 越界则无操作

if (i > 1){ // 检查是否是大小顶堆
if (nodes[i] > nodes[i / 2]) isMaxHeap = false;
else if(nodes[i] < nodes[i / 2]) isMinHeap = false;
}

path.push_back(nodes[i]); // 遍历当前结点

if (2 * i > n && 2 * i + 1 > n){ // 是叶子结点则输出当前遍历到的所有结点
auto it = path.begin();
printf("%d", *it);
it++;
while (it != path.end()){
printf(" %d", *it);
it++;
}
printf("\n");
}
else{ // 不是叶子结点
dfs(2 * i + 1); // 遍历右子树
dfs(2 * i); // 遍历左子树
}

path.pop_back(); // 回溯
}

int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++){ // 记录结点
scanf("%d", nodes+i);
}

dfs(1); // 深度优先遍历树并在过程中判断是否为大顶堆或小顶堆

if (isMaxHeap) printf("Max Heap");
else if (isMinHeap) printf("Min Heap");
else printf("Not Heap");
return 0;
}

作者:@臭咸鱼

转载请注明出处:https://www.cnblogs.com/chouxianyu/

欢迎讨论和交流!