1

题目大意:

给定一颗N个节点的完全二叉树的层次序列,需要输出该树的所有从根节点到叶子节点的路径(优先访问右子树),然后判断是否是堆,如果不是输出Not Heap,否则输出Max Heap或者Min Heap。

算法思路:

使用heap数组存储完全二叉树的层次遍历,无需做任何建树的操作,因为节点的下标之间自然存在父子关系,所以直接使用先序遍历遍历这课树,并且在访问每一个节点的时候使用path数组进行保存,在遇到叶子节点的时候就进行输出,节点访问完毕就回溯,该过程使用$preTraverse$函数来完成。紧接着就是使用$isMaxHeap$和$isMinHeap$变量标记当前完全二叉树是否是大根堆或者小根堆,初始为true,然后使用引用传值到$isMaxOrMinHeap$中,同时判断是否是大根堆或者小根堆,这里采用负向逻辑,只要有左孩子,左孩子小于根节点的说明不是小根堆,否则说明不是大根堆,右孩子亦然如此。最后根据$isMaxHeap$和$isMinHeap$的值进行相应的输出即可。

提交结果:

image.png

AC代码:

#include<cstdio>
#include<vector>

using namespace std;

int N;
int heap[1005];
vector<int> path;

void preTraverse(int root){
    if(root>N) return;
    // 先访问当前节点,因为这样就可以在遇到叶子节点的时候得到一个从根节点到叶子节点的路径
    path.push_back(heap[root]);
    if(2*root>N&&2*root+1>N){
        // 到达叶子节点,输出该路径即可
        for(int i=0;i<path.size();++i){
            printf("%d",path[i]);
            if(i<path.size()-1) printf(" ");
        }
        printf("\n");
    }
    preTraverse(2*root+1);
    preTraverse(2*root);
    path.pop_back();
}

void isMaxOrMinHeap(bool &isMaxHeap,bool &isMinHeap){
    for (int i = 1; i <= N; ++i) {
        if((2*i<=N&&heap[i]<heap[2*i])||(2*i+1<=N&&heap[i]<heap[2*i+1])){
            isMaxHeap = false;
        }
        if((2*i<=N&&heap[i]>heap[2*i])||(2*i+1<=N&&heap[i]>heap[2*i+1])){
            isMinHeap = false;
        }
    }
}

int main(){
    scanf("%d",&N);
    for (int i = 1; i <= N; ++i) {
        scanf("%d",&heap[i]);
    }
    postTraverse(1);
    bool isMaxHeap = true;
    bool isMinHeap = true;
    isMaxOrMinHeap(isMaxHeap,isMinHeap);
    if(isMaxHeap){
        printf("Max Heap");
    } else if(isMinHeap){
        printf("Min Heap");
    } else {
        printf("Not Heap");
    }
    return 0;
}


乔梓鑫
569 声望17 粉丝

主要分享个人学习经验和心得