题意分析:
给出一个1000以内的整数N,以及N个整数,并且这N个数是按照完全二叉树的层序遍历输出的序列,输出所有的整条的先序遍历的序列(根 右 左),以及判断整棵树是否是符合堆排序的规则(判断是大顶堆,小顶堆,不是堆)
题解分析:
由于给出的整数序列是按照完全二叉树的层序遍历,所以不存在中间有空的节点,并且层序遍历满足1~N的节点顺序正好方便我们一边输入一边建立完全二叉树,之后就是正常的先序遍历(这题要求根 右 左),有所区别的是最后的输出每次到达最后一个叶子节点的时候都需要输出一遍整条序列,所以我们用一个vector存储遍历的路径,关于是否是大顶堆小顶堆的判断其实就是比较每次的一条路径,如果所有的路径都是递增就是小顶堆,都是递减就是大顶堆,无论是同一条路径中出现了乱序还是有两条路径的排序规则不同都将导致堆的不存在,还有就是开范围的时候多开一倍不然就会越界哟~
代码:
1 #include<iostream> 2 #include<stdio.h> 3 #include<vector> 4 #include<string.h> 5 using namespace std; 6 7 const int N = 2005; 8 vector<int> road; //可能有相同大小的键值的节点 9 int tree[N]; 10 int n, flag, appear; 11 12 void pre(int gen){ 13 road.push_back(tree[gen]); 14 if(tree[gen*2] == 0 && tree[gen*2+1] == 0){ 15 int up = 0; int down = 0; 16 for(int i = 0; i < road.size(); i++){ 17 if(i != 0) printf(" "); 18 printf("%d", road[i]); 19 if(i > 0 && road[i] > road[i-1]) up = 1; //出现递增 20 if(i > 0 && road[i] < road[i-1]) down = 1; //出现递降 21 } 22 if(appear == 0){ 23 if(up == 1 && down == 0){ 24 appear = 1; flag = -1; 25 } 26 if(up == 0 && down == 1){ 27 appear = 1; flag = 1; 28 } 29 if(up == 1 && down == 1){ 30 appear = 1; flag = 0; 31 } 32 }else{ 33 if(flag == 1 && up == 1) flag = 0; 34 if(flag == -1 && down == 1) flag = 0; 35 } 36 printf(" "); 37 road.pop_back(); 38 return; 39 } 40 if(tree[gen*2+1] != 0) pre(gen*2+1); 41 if(tree[gen*2] != 0) pre(gen*2); 42 road.pop_back(); 43 } 44 45 int main(){ 46 scanf("%d", &n); 47 memset(tree, 0, sizeof(tree)); 48 for(int i = 1; i <= n; i++) scanf("%d", &tree[i]); 49 appear = 0; //是否和flag比较过 0没有 1比较过 50 flag = 0; //1为大顶堆 -1为小顶堆 0为都不是 51 pre(1); 52 if(flag == 0) printf("Not Heap "); 53 if(flag == 1) printf("Max Heap "); 54 if(flag == -1) printf("Min Heap "); 55 return 0; 56 }