PAT甲級 堆 相關題_C++題解

目錄

  • 《算法筆記》重點摘要
  • 1147 Heaps (30)
  • 1155 Heap Paths (30)

《算法筆記》 9.7 堆 重點摘要

1. 定義

堆是徹底二叉樹,樹中每一個結點的值不小於(或不大於)其左右子結點的值,稱之爲大頂堆(或小頂堆)ios

const int maxn = 100;
int heap[maxn], n = 10; // heap 爲堆,n 爲元素個數

2. 向下調整

// 對 heap 數組在 [low,high] 範圍進行向下調整
// 其中 low 爲欲調整結點的數組下標, high 通常爲堆的最後一個元素的數組下標
void downAdjust(int low, int high){
    int i = low, j = i * 2; // i 爲欲調整結點,j 爲其左子結點
    while (j <= high){  // 存在子結點時進行循環
        if (j + 1 <= high && heap[j+1] > heap[j)    // 若右子結點存在且值大於左子結點
            j = j + 1;
        if (heap[j] > heap[i]){ // 若子結點中最大的值比欲調整結點 i 的值大
            swap(heap[j], heap[i]);
            i = j;
            j = i * 2;
            // 保持 i 爲欲調整結點,j 爲其左子結點
        }
        else break;
    }
}

3. 建堆

  • 徹底二叉樹葉子結點數爲 ceil(n/2)
  • 數組下標在 [1,floor(n/2)] 內均爲非葉子節點
  • 從 floor(n/2) 開始倒着枚舉結點,對每一個結點 i 進行 [i,n] 範圍調整
  • 保證每一個節點都是以其爲根結點的子樹中值最大的結點
void createHeap(){
    for (int i = n / 2; i >= 1; i--)
        downAdjust(i,n);
}

4. 刪除堆頂元素

用最後一個元素覆蓋堆頂元素,再對根結點進行調整算法

void deleteTop(){
    heap[1] == heap[n--];   // 覆蓋後元素個數 --
    downAdjust(1,n);
}

5. 向上調整

// 對 heap 數組在 [low,high] 範圍進行向上調整
// 其中 low 通常設置爲 1, high 爲欲調整結點的數組下標
void upAdjust(int low, int high){
    int i = high, j = i / 2;    // i 爲欲調整結點,j 爲其父結點
    while (j >= low){   // 父結點在 [low,high] 範圍內
        if (heap[j] < heap[i]){   // 父結點值小於欲調整結點值
            swap(heap[j],heap[i]);
            i = j;
            j = i / 2;
            // 保持i 爲欲調整結點,j 爲其父結點
        }
        else break;
    }
}

6. 添加元素

void insert(int x){
    heap[++n] = x;
    upAdjust(1,n);
}

7. 堆排序

  • 倒着遍歷數組
  • 訪問到 i 位置時,將堆頂元素與 i 位置元素交換,則 i 位置固定爲 [1,i] 最大值
  • 在 [1,i-1] 範圍對堆頂元素進行向下調整
void heapSort(){
    createHeap();
    for (int i = n; i > 1; i++){
        swap(heap[i], heap[1]);
        downAdjust(1, i-1);
    }
}

8. 遞推判斷堆類型方法

bool isMax = true, isMin = true;
for (int i = 2; i <= n; i++) {
    if (tree[i/2] > tree[i]) isMin = false;
    if (tree[i/2] < tree[i]) isMax = false;
}
printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");

1147 Heaps (30)

題目思路

  • 遞推 判斷堆類型,兩個變量分別記錄是否符合大頂堆 / 小頂堆
  • 遞歸 保存後序遍歷序列,按要求輸出,注意每檢查一個新的堆要將保存後序序列的容器清空 post.clear()
#include<iostream>
#include<vector>
using namespace std;
int n;
vector<int> tree, post;
void postorder(int index){
    if (index > n) return;
    postorder(index * 2);
    postorder(index * 2 + 1);
    post.push_back(tree[index]);
}
int main()
{
    int m, data;
    scanf("%d%d", &m, &n);
    tree.resize(n+1);
    for (int i = 0; i < m; i++){
        for (int j = 1; j < n + 1; j++) scanf("%d", &tree[j]);
        bool isMax = true, isMin = true;
        for (int j = 2; j < n + 1; j++){
            if (tree[j/2] > tree[j]) isMin = false;
            if (tree[j/2] < tree[j]) isMax = false;
        }
        printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");
        post.clear();
        postorder(1);
        for (int j = 0; j < post.size(); j++)
            printf("%d%c", post[j], j + 1 == post.size() ? '\n' : ' ');
    }
    return 0;
}

1155 Heap Paths (30)

題目思路

  • DFS 遞歸 輸出路徑
    • 終止條件:到葉結點(2 * index > n),輸出路徑
    • 進入下一層條件:下一層的子結點存在
    • 即遞歸確認下一個結點存在時才進入,能進入遞歸的都是存在非越界的結點,因此經過其子結點越界判斷到葉結點,輸出到此結點的路徑
  • 遞歸 判斷是什麼堆
    • 每進入一個非根節點的結點,就判斷它與父結點的大小關係
    • 不符合大頂堆或小頂堆的就將對應變量置 false,符合要求的沒有機會被置 false
    • 最後根據變量輸出判斷結果
#include<iostream>
#include<vector>
using namespace std;
int n, tree[1001];;
bool isMax = true, isMin = true;
vector<int> path;
void DFS(int index){
    if (index > 1){
        if (tree[index] > tree[index/2]) isMax = false;
        if (tree[index] < tree[index/2]) isMin = false;
    }
    if (2 * index > n){
        for (int i = 0; i < path.size(); i++)
            printf("%d%c", tree[path[i]], i == path.size()-1 ? '\n' : ' ');
        return;
    }
    if (2 * index + 1 <= n){
        path.push_back(2 * index + 1);
        DFS(2 * index + 1);
        path.pop_back();
    }
    path.push_back(2 * index);
    DFS(2 * index);
    path.pop_back();
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%d", &tree[i+1]);
    path.push_back(1);
    DFS(1);
    printf("%s\n", isMax ? "Max Heap" : isMin ? "Min Heap" : "Not Heap");
    return 0;
}
相關文章
相關標籤/搜索