性质
对二叉查找树进行中序遍历,遍历的结果是有序的。
题目1:Is It a Binary Search Tree
https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856
自己写的(多点的,建两棵树)
省题
输入先序数组,按照先序数组建BST树/BST镜像树。
若该数组确实是BST树/BST镜像树的先序数组,那么输出YES,再输出相对应(BST树/BST镜像树)树的后序数组
- 这里BST的定义标准
a)The left subtree of a node contains only nodes with keys less than the node’s key.
b)The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
c)Both the left and right subtrees must also be binary search trees
小于根节点的在左子树没变;但是右子树的性质变为了大于等于根节点 - 镜像BST树的定义
If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.
如果我们交换每个节点的左右子树,那么得到的树就称为BST的镜像。
.
思路
设bool flag=false,若有 为BST/镜像BST的先序数组 其中一条满足则为true
根据先序数组建树,若为BST的先序数组,flag=true
若flag=false,再根据先序数组建镜像树,若为镜像BST的先序数组,flag=true
若flag=true则YES,按后序遍历输出,否则NO
根据镜像BST的定义可知,镜像BST左右孩子的定义与BST正相反,即
大于等于根节点的在左子树;小于根节点的在右子树
按照建树的函数及其过程如法炮制建镜像树的函数及其过程
AC代码
//根据先序建BST(第一个元素为根),判断该BST的先序是否为输入的先序
//如果是的,就输出后序
#include<bits/stdc++.h>
using namespace std;
const int maxv=1010;
struct node{
int data;
node* lchild;
node* rchild;
};
int n,pre[maxv],step;
//新建结点
node* newnode(int x)
{
node* root=new node;
root->data=x;
root->lchild=root->rchild=NULL;
return root;
}
//插入
void insert(node* &root,int x)
{
if(root==NULL){
root=newnode(x);
return;
}
//省题
/*The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than or equal to the node's key.*/
else if(x<root->data)//小于根节点,在其左子树
insert(root->lchild,x);
else if(x>=root->data)
insert(root->rchild,x);
}
//镜像插入
void Minsert(node* &root,int x)
{
if(root==NULL){
root=newnode(x);
return;
}
//省题
/*If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.*/
else if(x>=root->data)//大于等于根节点,在其左子树(和原来的相反)
Minsert(root->lchild,x);
else if(x<root->data)
Minsert(root->rchild,x);
}
//建树
node* create()
{
node* root=NULL;
for(int i=1;i<=n;i++)
insert(root,pre[i]);
return root;
}
//镜像建树
node* Mcreate()
{
node* root=NULL;
for(int i=1;i<=n;i++)
Minsert(root,pre[i]);
return root;
}
bool preDFS(int &step,node* root)
{
if(pre[step]!=root->data)
return false;
if(root->lchild!=NULL)
if(!preDFS(++step,root->lchild))
return false;
if(root->rchild!=NULL)
if(!preDFS(++step,root->rchild))
return false;
return true;
}
void postDFS(node* root,node *R)
{
if(root->lchild!=NULL)
postDFS(root->lchild,R);
if(root->rchild!=NULL)
postDFS(root->rchild,R);
printf("%d%s",root->data,root==R?"\n":" ");
}
int main(){
while(scanf("%d",&n)!=EOF){
bool flag=false;
for(int i=1;i<=n;i++)
scanf("%d",&pre[i]);
node* root=create();
step=1;
if(preDFS(step,root))
flag=true;
if(!flag){
step=1;
root=Mcreate();
if(preDFS(step,root))
flag=true;
}
if(flag){
printf("YES\n");
postDFS(root,root);
}
else
printf("NO\n");
}
return 0;
}
小蓝书上的(单点的,根据BST写两种的先序序列)
不同于我自己写的:建两棵树分别判断
小蓝书上写的是:建一棵树,根据这棵树遍历出BST/镜像BST的先序序列
根据BST遍历出镜像BST的先序序列就是把左右根的遍历顺序交换为右左根,来满足镜像BST和BST的左右孩子相反的定义
AC代码
#include<bits/stdc++.h>
using namespace std;
struct node {
int data; //数据域
node *left,*right; //指针域
} ;
void insert(node* &root, int data) {
if (root == NULL) {//到达空结点时, 即为需要插入的位置
root = new node;
root->data = data;
root->left = root->right = NULL;//此句不能漏
return;
}
if (data < root->data)//插在左子树
insert (root->left, data);
else//插在右子树
insert(root->right, data);
}
//先序遍历, 结果存在vi
void preOrder(node* root, vector<int>&vi) {
if(root == NULL)
return;
vi.push_back(root->data);
preOrder(root->left,vi);
preOrder(root->right,vi);
}
//镜像树先序遍历, 结果存放于vi
void preOrderMirror(node* root, vector<int>&vi) {
if(root == NULL)
return;
vi.push_back(root->data);
preOrderMirror(root->right, vi);
preOrderMirror(root->left, vi);
}
//后序遍历, 结果存放于vi
void postOrder(node* root,vector<int>&vi) {
if(root == NULL)
return;
postOrder(root->left, vi);
postOrder(root->right, vi);
vi.push_back(root->data);
}
//镜像树后序遍历, 结果存放于vi
void postOrderMirror(node* root, vector<int>&vi) {
if(root == NULL)
return;
postOrderMirror(root->right, vi);
postOrderMirror(root->left, vi);
vi.push_back(root->data);
}
//origin 存放初始序列
//pre、post 为先序、后序, preM、postM 为镜像树先序、后序
vector<int> origin, pre, preM, post, postM;
int main() {
int n, data;
node* root=NULL;//定义头结点
scanf ("%d", &n);//输入结点个数
for(int i = 0; i < n; i++) {
scanf("%d", &data);
origin.push_back(data);//将数据加入origin
insert(root, data);//将data 插入二叉树
}
preOrder(root, pre); //求先序
preOrderMirror(root, preM); //求镜像树先序
postOrder(root, post); //求后序
postOrderMirror (root, postM); //求镜像树后序
if (origin == pre) { //初始序列等于先序序列
printf("YES\n");
for (int i = 0; i < post.size(); i++) {
printf ("%d", post[i]);
if(i < post.size() -1)
printf(" ");
}
} else if(origin == preM) { //初始序列等于镜像树先序序列
printf("YES\n");
for (int i = 0; i < postM. size(); i++) {
printf("%d", postM[i]);
if(i <postM.size() -1)
printf(" ");
}
} else {
printf("NO\n"); //否则输出NO
}
return 0;
}