本博客是用二叉排序树实现map的查找操作。
一:二叉排序树的性质:
(1)若它的左子树非空,则其左子树所有结点的关键字的值均小于其根结点的关键字值。
(2)若它的右子树非空,则其右子树所有结点的关键字的值均大于其根结点关键字的值。
(3)它的左右子树也分别为一棵二叉排序树。
二:二叉树的插入和建立
基本思想:(1)若二叉树为空,则新结点作为二叉排序树的根节点。
(2)若给定结点的关键字的值小于根节点关键字的值,则插入到左子树中。
(3)若给定结点的关键字的值大于根节点关键字的值,则插入到右子树中。
三:二叉树的删除(删除结点后还要保留二叉树的性质)
假设待删除的结点为*p(指向结点的指针为p),假设指针f指向结点*p的双亲,s指向结点*p的左子树中关键字值最大的结点,q指向*s的双亲。
(1)当*p为叶子结点时,即左右子树均为空。
由于删除叶子结点不破坏整棵树的结构,则值需将其双亲结点*f的lchild或rchild置空即可,然后删除结点。
(2)当*p结点只有一颗非空子树,或者是非空左子树,或者是非空右子树。
若*p结点只有右子树而无左子树,则用其右子树的根节点取代要删除的*p结点。
若*p结点只有左子树而无右子树,则用其左子树的根节点取代要删除的*p结点。
(3)当*p结点的左右子树均为空。
由图(a)可知,在删除*p结点之前,中序遍历该二叉树得到的序列为{……(CL)C……(QL)Q(SL)SP(PR)F……},在删去*p之后,为保持其他元素之间相对位置保持不变,可以令*p的直接前驱(或直接后继)替代*p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。如图(b)所示,当以直接前驱*s替代*p时,由于*s只有左子树(SL),则在删去*s之后,只要令(SL)为*s的双亲*q的右子树即可。
四:具体代码:
#include<stdio.h>
#include<algorithm>
#include<iostream>
#include<set>
#include<map>
#include<cmath>
#include<string>
#include<string.h>
#include<math.h>
#include<vector>
#include<queue>
#define maxn 100010
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int a,b;
node *left,*right,*pre;
node()
{
left=NULL;
right=NULL;
}
};
int flag=0;
node *root=NULL;
void Add(int x,int y)
{
node *t,*p;
t=new node();
t->a=x;
t->b=y;
p=root;
while(1)
{
if(t->a < p->a)
{
if(p->left==NULL)
{
t->pre=p;
p->left=t;
break;
}
else
p=p->left;
}
else if(t->a > p->a)
{
if(p->right == NULL)
{
p->pre=p;
p->right = t;
break;
}
else
p=p->right;
}
else
{
p->b = t->b;
break;
}
}
return ;
}
void Display(node *p)//中序遍历输出这棵树
{
if(p == NULL)
return ;
Display(p->left);
cout<< p->a <<" : "<< p->b <<endl;
Display(p->right);
}
int Query(int x)
{
node *p=root;
while(1)
{
if(x== p->a)
{
return p->b;
}
if(x > p->a)
{
if(p->right==NULL)
return -1;
p=p->right;
}
else
{
if(p->left == NULL)
return -1;
p=p->left;
}
}
}
node *ans;
node* CC(node *p,int x)//找中序遍历的后继
{
if(p->left!=NULL)
CC(p->left,x);
if(flag==1)
{
ans=p;
flag=0;
}
if(p->a==x)
flag=1;
if(p->right!=NULL)
CC(p->right,x);
}
void Delete(int x)
{
if(Query(x)==-1)
return ;
flag=0;
node *p=root;
while(1)//先找到后继这个结点
{
if(p->a == x)
break;
if(x<p->a)
p=p->left;
else
p=p->right;
}
if(p->left==NULL && p->right == NULL)//为叶子结点
{
if(p->pre->left->a == x)
p->pre->left=NULL;
else
p->pre->right=NULL;
delete p;
}
else if(p->left == NULL || p->right == NULL)//只有一颗子树
{
if(p->left == NULL)
p->pre->right=p->right;
else
p->pre->left=p->left;
delete p;
}
else//有两颗子树
{
node *q;
CC(root,x);
q=ans;
p->a=q->a;
p->b=q->b;
cout<<"q->a : "<<x<<" "<<q->a<<endl;
if(q->left == NULL && q->right == NULL)
{
if(q->pre->left->a == p->a)
q->pre->left=NULL;
if(q->pre->right->a== p->a)
q->pre->right=NULL;
delete q;
}
else{
q->pre->right=q->right;
delete q;
}
}
return ;
}
int main()
{
int x,y,n;
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>x>>y;
if(i==1)
{
root=new node();
root->a = x;
root->b = y;
}
else
Add(x,y);
}
Display(root);
cout<<"输入您要查询结点的值:"<<endl;
cin>>x;
int ans=Query(x);
if(ans!=-1)
cout<<ans<<endl;
else
cout<<"此节点不存在"<<endl;
cout<<"输入您要删除的值:"<<endl;
cin>>x;
Delete(x);
Display(root);
return 0;
}