问题 A: 算法9-9~9-12:平衡二叉树的基本操作
时间限制: 1 Sec 内存限制: 32 MB
提交: 295 解决: 127
[提交][状态][讨论版][命题人:外部导入]
题目描述
平衡二叉树又称AVL树,它是一种具有平衡因子的特殊二叉排序树。平衡二叉树或者是一棵空树,或者是具有以下几条性质的二叉树:
1. 若它的左子树不空,则左子树上所有结点的值均小于它的根节点的值;
2. 若它的右子树不空,则右子树上所有结点的值均大于它的根节点的值;
3. 它的左右子树也分别为平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。
若将二叉树上结点的平衡因子定义为该结点的左子树深度减去它的右子树的深度,则平衡二叉树上的所有结点的平衡因子只可能为-1、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则这棵二叉树就是不平衡的。
通过平衡二叉树的性质不难得知,其插入、删除、查询都操作的时间复杂度均为O(log2n)。
维持平衡二叉树性质的操作可以被称为旋转。其中平衡二叉树的右旋处理可以描述如下:
而其左旋处理与右旋正好相反,可以描述如下:
在本题中,读入一串整数,首先利用这些整数构造一棵平衡二叉树。另外给定多次查询,利用构造出的平衡二叉树,判断每一次查询是否成功。
输入
输入的第一行包含2个正整数n和k,分别表示共有n个整数和k次查询。其中n不超过500,k同样不超过500。
第二行包含n个用空格隔开的正整数,表示n个整数。
第三行包含k个用空格隔开的正整数,表示k次查询的目标。
输出
只有1行,包含k个整数,分别表示每一次的查询结果。如果在查询中找到了对应的整数,则输出1,否则输出0。
请在每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
8 3
1 3 5 7 8 9 10 15
9 2 5
样例输出
1 0 1
提示
在本题中,首先需要按照题目描述中的算法完成平衡二叉树的构造过程,之后需要通过在平衡二叉树中的不断向下查找,将需要查询的值与当前节点的值进行比较,直到确定被查询的值是否存在。
通过课本中的性能分析部分,不难发现平衡二叉树的查找、插入、删除等操作的时间复杂度均为O(log2n),这是通过利用旋转操作使二叉树保持平衡状态而保证的。
//注意 等于1 -1的分支要写清楚 不能直接else收留所有剩下情况 会运行错误
if(getBlanceFactor(root->lchild)==1){//LL
R(root);
}else if(getBlanceFactor(root->lchild)==-1){//LR
L(root->lchild);
R(root);
}if(getBlanceFactor(root->lchild)==1){//LL
R(root);
}else {//LR 运行错误50% 可能还有其他分支。。。。?0? 当然写出来肯定安全一点
L(root->lchild);
R(root);
}
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int data,height;
node *lchild,*rchild;
};
node* newNode(int v){
node* Node=new node;
Node->data=v;
Node->rchild=Node->lchild=NULL;
Node->height=1;
return Node;
}
int getHeight(node* root){
if(root==NULL) return 0;
else return root->height;
}
int getBlanceFactor(node* root){
return getHeight(root->lchild)-getHeight(root->rchild);
}
void updateHeight(node* root){
// root->height=max(root->lchild->height,root->rchild->height)+1;
//注意为了防止左右孩子不存在 要调用封装的getHeight方法来获取高度
root->height=max(getHeight(root->lchild),getHeight(root->rchild))+1;
}
bool search(node* root,int v){
if(root==NULL) return false;
if(v==root->data) return true;
if(v<root->data) search(root->lchild,v);
else search(root->rchild,v);
}
void L(node* &root){
node* temp=root->rchild;
root->rchild=temp->lchild;
temp->lchild=root;
updateHeight(root);
updateHeight(temp);
root=temp;
}
void R(node* &root){
node* temp=root->lchild;
root->lchild=temp->rchild;
temp->rchild=root;
updateHeight(temp);
updateHeight(root);
root=temp;
}
void insert(node* &root,int v){
if(root==NULL){
root=newNode(v);
return;
}
if(v<root->data){
insert(root->lchild,v);
updateHeight(root);
//调整平衡状态
if(getBlanceFactor(root)==2){
if(getBlanceFactor(root->lchild)==1){//LL
R(root);
}else if(getBlanceFactor(root->lchild)==-1){//LR
L(root->lchild);
R(root);
}
}
}else{//往右边插入
insert(root->rchild,v);
updateHeight(root);//更新root别错了★
if(getBlanceFactor(root)==-2){
if(getBlanceFactor(root->rchild)==-1){//RR
L(root);
}else if(getBlanceFactor(root->rchild)==1){//RL 必须写出来 不能直接就else分支了 否则报错
R(root->rchild);
L(root);
}
}
}
}
int main(){
// freopen("input.txt","r",stdin);
int n,k;
node* root;
int x;
while(cin>>n>>k){
root=NULL;
while(n--){
cin>>x;
insert(root,x);
}
while(k--){
cin>>x;
cout<<search(root,x)<<" ";
}
cout<<endl;
}
return 0;
}
本题500,范围内数据太弱,直接暴力也能过
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
// freopen("input.txt","r",stdin);
int a[510],n,k,x;
while(cin>>n>>k){
for(int i=0;i<n;i++) cin>>a[i];
while(k--){
cin>>x;
if(find(a,a+n,x)!=a+n) cout<<"1 ";
else cout<<"0 ";
}
cout<<endl;
}
return 0;
}