【PAT甲级 堆/堆的判断/树的遍历 C++】1147 Heaps (30 分)

使用DFS

# include <bits/stdc++.h>
using namespace std;

int M, N;
vector<int> A(1001); 

// 使用DFS遍历树,每次都只判断当前结点u和它的左后孩子符不符合堆的要求
void DFS(int u, int &flag){
    if(u == 1){ // 初始化第一次
        if(N == 2) {
            if(A[u] >= A[u*2]) flag = 2;
            else 
            if(A[u] <  A[u*2]) flag = 1;
        } 
        else {
            if(A[u] >= A[u*2] && A[u] >= A[u*2 + 1]) flag = 2;
            else
            if(A[u] <  A[u*2] && A[u] <  A[u*2 + 1]) flag = 1;
            else                                     flag = 0;
        }

    }
    else { //然后后面每一次的判断都根据前一次的flag来判断,如果上一次的flag和这一次的要求不一致,说明not heap
        if(u > N) return;
        if(u*2 <= N){ // 不是叶子结点
            if(u*2 + 1 <= N){ // 有左右孩子(有右孩子,那必然有左孩子)
                if(flag == 2 && A[u] >= A[u*2] && A[u] >= A[u*2 + 1]) flag = 2; // 当前结点仍符合大根堆
                else
                if(flag == 1 && A[u] <  A[u*2] && A[u] <  A[u*2 + 1]) flag = 1; // 当前结点仍符合小根堆
                else                                                  flag = 0; // 当前结点既不是大根堆也不是小根堆,那就不是堆
            } else { // 只有左孩子
                if(flag == 2 && A[u] >= A[u*2]) flag = 2;
                else
                if(flag == 1 && A[u] <  A[u*2]) flag = 1;
                else                            flag = 0;

            }
        } else { // 是叶子结点
            return;
        }
    }
    if(flag == 0) return; // 当前结点表明该序列不是堆,直接返回。

    DFS(u*2    , flag); // 向左子树递归
    DFS(u*2 + 1, flag); // 向右子树递归
}

int cnt;
void postTraverse(int root){ // 后序遍历
    if(root > N) return;
    postTraverse(root*2);
    postTraverse(root*2 + 1);
    cout << A[root] << (cnt++ == N-1 ? "\n" : " ");
}

int main() {
    cin >> M >> N;
    for(int i = 0;i < M;++i){
        for(int j = 1;j <= N;++j)
            cin >> A[j];

        int flag;
        DFS(1, flag);

        if(flag == 2){
            cout << "Max Heap" << endl; 
        } else
        if(flag == 1){
            cout << "Min Heap" << endl;
        } else
        if(flag == 0) {
            cout << "Not Heap" << endl;
        }
        cnt = 0;
        postTraverse(1);
    }

    return 0;
}

使用algorithm中的is_heap函数

# include <bits/stdc++.h>
using namespace std;

int M, N;
vector<int> A(1001); 

int cnt;
void postTraverse(int root){ // 后序遍历
    if(root > N) return;
    postTraverse(root*2);
    postTraverse(root*2 + 1);
    cout << A[root] << (cnt++ == N-1 ? "\n" : " ");
}

int main() {
    cin >> M >> N;
    A.resize(N+1);
    for(int i = 0;i < M;++i){
        for(int j = 1;j <= N;++j)
            cin >> A[j];

        bool isMaxHeap = is_heap(A.begin()+1, A.end());
        bool isMinHeap = is_heap(A.begin()+1, A.end(), greater<int>());
        
        if(isMaxHeap){
            cout << "Max Heap" << endl; 
        } else
        if(isMinHeap){
            cout << "Min Heap" << endl;
        } else
        if(!isMaxHeap && !isMinHeap) {
            cout << "Not Heap" << endl;
        }
        cnt = 0;
        postTraverse(1);
    }

    return 0;
}

从后往前遍历判断当前结点是否大于等于父节点,否的话说明不是大根堆,返回false;
从后往前遍历判断当前结点是否小于父节点,否的话说明不是小根堆,返回false;

如果既不是大根堆也不是小根堆,那么说明就不是堆。

自写is_heap函数

# include <bits/stdc++.h>
using namespace std;

int M, N;
vector<int> A(1001); 

int cnt;
void postTraverse(int root){ // 后序遍历
    if(root > N) return;
    postTraverse(root*2);
    postTraverse(root*2 + 1);
    cout << A[root] << (cnt++ == N-1 ? "\n" : " ");
}

bool is_max_heap(){
    for(int i = N;i >= 2;--i)
        if(A[i/2] < A[i])
            return false;
    return true;
}
bool is_min_heap(){
    for(int i = N;i >= 2;--i)
        if(A[i/2] >= A[i])
            return false;
    return true;
}

int main() {
    cin >> M >> N;
    A.resize(N+1);
    for(int i = 0;i < M;++i){
        for(int j = 1;j <= N;++j)
            cin >> A[j];

        bool isMaxHeap = is_max_heap();
        bool isMinHeap = is_min_heap();
        
        if(isMaxHeap){
            cout << "Max Heap" << endl; 
        } else
        if(isMinHeap){
            cout << "Min Heap" << endl;
        } else
        if(!isMaxHeap && !isMinHeap) {
            cout << "Not Heap" << endl;
        }
        cnt = 0;
        postTraverse(1);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值