1. 程式人生 > 實用技巧 >PAT甲級1155Heap Paths

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. 最後輸出該樹是否是大小頂堆

程式碼

// 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/

歡迎討論和交流!