PAT甲級 二叉查找樹 相關題_C++題解

二叉查找樹

PAT (Advanced Level) Practice 二叉查找樹 相關題node

目錄

  • 《算法筆記》 重點摘要
  • 1099 Build A Binary Search Tree (30)
  • 1115 Counting Nodes in a BST (30)
  • 1143 Lowest Common Ancestor (30)

《算法筆記》 9.4 二叉查找樹 重點摘要

二叉查找樹靜態實現 ⭐

(1) 定義
struct Node{
    typename data;
    int level;
    int lchild;
    int rchild;
} node[MAXN];
(2) 新建結點
int index = 0;
int newNode (int value){
//    node[index] = {value,-1,-1};
    node[index].data = value;
    node->lchild = node->rchild = -1;
    return index++;
}
(3) 插入
void insert (int &root, int value){
    if (root == -1){
        root = newNode(value);
        return;
    }
    if (root->data == value) return;
    else if (root->data > value) insert(root->lchild, value);
    else insert(root->rchild, value);
}
(4) 建立
int create (int value[], int n){
    int root = -1;
    for (int i = 0; i < n; i++) insert(root, value[i]);
    return root;
}
(5) 查找&修改
void search (int root, int value, int newvalue){
    if (root == -1) return;
    if (root->data == value) root->data = newvalue;
    else if (root->data > value) search(root->lchild, value, newvalue);
    else search(root->rchild, value, newvalue);
}
(6) 刪除
int findMax (int root){
    while (root->rchild != -1) root = root->rchild;
    return root;
}
int findMin (int root){
    while (root->lchild != -1) root = root->lchild;
    return root;
}
void deleteNode (int &root, int value){
    if (root == -1) return;
    if (root->data == value){
        if (root->lchild == -1 && root->rchild == -1)
            root = -1;
        else if (root->lchild != -1){
            int pre = findMax(root->lchild);
            root->data = pre->data;
            deleteNode(root->lchild, pre->data);
        }
        else{
            int next = findMin(root->rchild);
            root->data = next->data;
            deleteNode(root->rchild, next->data);
        }
    }
    else if (root->data > value) deleteNode(root->lchild, value);
    else deleteNode(root->rchild, value);
}

1099 Build A Binary Search Tree (30)

題目思路

  • 主要須要樹的結構,其中數據須要後面填,用 vector<pair<int,int>> 儲存結點對應左右子結點便可
  • 將樹結構接收進來後先中序遍歷,獲得樹結點序號對應的中序序列
  • 再將數值接收進來,升序排列即爲中序遍歷
  • 以上可將結點序號和數值對應起來,爲便於查找,開一個 match 容器,將數值填到結點序號對應位置
  • 對樹做層序遍歷,從隊列中彈出結點時將對應的數值壓入容器,最後按要求輸出
#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
vector<pair<int,int>> tree;
vector<int> in, level, data, match;
void inorder(int root){
    if (root == -1) return;
    inorder(tree[root].first);
    in.push_back(root);
    inorder(tree[root].second);
}
void levelorder(int root){
    queue<int> q;
    q.push(root);
    while (!q.empty()){
        int now = q.front();
        level.push_back(match[now]);
        q.pop();
        if (tree[now].first != -1) q.push(tree[now].first);
        if (tree[now].second != -1) q.push(tree[now].second);
    }
}
int main()
{
    int n;
    scanf("%d", &n);
    tree.resize(n);
    for (int i = 0; i < n; i++)
        scanf("%d%d", &tree[i].first, &tree[i].second);
    data.resize(n);
    for (int i = 0; i < n; i++)
        scanf("%d", &data[i]);
    sort(data.begin(), data.end());
    inorder(0);
    match.resize(n);
    for (int i = 0; i < n; i++) match[in[i]] = data[i];
    levelorder(0);
    for (int i = 0; i < n; i++) printf("%d%c", level[i], i+1 == n ? '\n' : ' ');
    return 0;
}

1115 Counting Nodes in a BST (30)

  • 注意:當樹退化成一條鏈時,若根從1開始,則樹深度有1000,levelnum 數組大小開爲 1000 會越界=》根節點層數從 0 開始
#include<iostream>
using namespace std;
struct Node{
    int data, lchild, rchild;
} node[1000];
int index = 0, depth = -1, levelnum[1000] = {0};
void insert(int &root, int value){
    if (root == -1){
        node[index] = {value, -1, -1};
        root = index++;
    }
    else if (node[root].data >= value) insert(node[root].lchild, value);
    else insert(node[root].rchild, value);
}
void DFS(int root, int level){
    levelnum[level]++;
    if (level > depth) depth = level;
    if (node[root].lchild != -1) DFS(node[root].lchild, level+1);
    if (node[root].rchild != -1) DFS(node[root].rchild, level+1);
}
int main()
{
    int n, data, root = -1;
    scanf("%d", &n);
    for (int i = 0; i < n; i++){
        scanf("%d", &data);
        insert(root, data);
    }
    DFS(0,0);
    printf("%d + %d = %d\n", levelnum[depth], levelnum[depth-1], levelnum[depth]+levelnum[depth-1]);
    return 0;
}

1143 Lowest Common Ancestor (30)

題目思路

  • LCA 的性質:大於一個子節點,小於另外一個子節點
  • 題目給出先序遍歷
  • 依次判斷是否符合 LCA 性質
  • 因爲可能一個點是另外一個點的祖先,應當容許 == 狀況
  • ?爲何按先序遍歷能獲得呢orz
#include<iostream>
#include<vector>
#include<unordered_map>
using namespace std;
int main()
{
    int m, n, u, v, root;
    scanf("%d%d", &m, &n);
    vector<int> pre(n);
    unordered_map<int,bool> keys;
    for (int i = 0; i < n; i++){
        scanf("%d", &pre[i]);
        keys[pre[i]] = true;
    }
    for (int i = 0; i < m; i++){
        scanf("%d%d", &u, &v);
        if (!keys[u] && !keys[v]) printf("ERROR: %d and %d are not found.\n", u, v);
        else if (!keys[u]) printf("ERROR: %d is not found.\n", u);
        else if (!keys[v]) printf("ERROR: %d is not found.\n", v);
        else{
            for (root = 0; root < n; root++)
                if ((pre[root] >= u && pre[root] <= v) || (pre[root] <= u && pre[root] >= v)) break;
            if (pre[root] == u || pre[root] == v) printf("%d is an ancestor of %d.\n", pre[root]==u?u:v, pre[root]==u?v:u);
            else printf("LCA of %d and %d is %d.\n", u, v, pre[root]);
        }
    }
    return 0;
}

附:

二叉查找樹鏈式實現

(1) 定義
struct Node{
    typename data;
    int level
    Node* lchild;
    Node* rchild;
}
(2) 新建結點
Node* newNode (int value){
    Node* node = new Node;
    node->data = value;
    node->lchild = node->rchild = NULL;
    return node;
}
(3) 插入
void insert (Node* &root, int value){
    if (root == NULL){
        root = newNode(value);
        return;
    }
    if (root->data == value) return;
    else if (root->data > value) insert(root->lchild, value);
    else insert(root->rchild, value);
}
(4) 建立
Node* create (int value[], int n){
    node* root = NULL;
    for (int i = 0; i < n; i++) insert(root, value[i]);
    return root;
}
(5) 查找&修改
void search (Node* root, int value, int newvalue){
    if (root == NULL) return;
    if (root->data == value) root->data = newvalue;
    else if (root->data > value) search(root->lchild, value, newvalue);
    else search(root->rchild, value, newvalue);
}
(6) 刪除
Node* findMax (Node* root){
    while (root->rchild != NULL) root = root->rchild;
    return root;
}
Node* findMin (Node* root){
    while (root->lchild != NULL) root = root->lchild;
    return root;
}
void deleteNode (Node* root, int value){
    if (root == NULL) return;
    if (root->data == value){
        if (root->lchild == NULL && root->rchild == NULL)
            root = NULL;
        else if (root->lchild != NULL){
            Node* pre = findMax(root->lchild);
            root->data = pre->data;
            deleteNode(root->lchild, pre->data);
        }
        else{
            Node* next = findMin(root->rchild);
            root->data = next->data;
            deleteNode(root->rchild, next->data);
        }
    }
    else if (root->data > value) deleteNode(root->lchild, value);
    else deleteNode(root->rchild, value);
}
相關文章
相關標籤/搜索