PAT甲级 二叉查找树 相关题_C++题解

二叉查找树

PAT (Advanced Level) Practice 二叉查找树 相关题

目录

  • 《算法笔记》 重点摘要
  • 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);
}
posted @ 2019-09-09 18:33  鲸90830  阅读(344)  评论(0编辑  收藏  举报