//bf=右子树-左子树,删除时用左子树的中序最后一个结点填充
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
struct Node{
int bf;
int data;
Node* left;
Node* right;
Node():bf(0),left(NULL),right(NULL){}
};
void RR(Node* &ptr){ //左单旋转
Node* subL=ptr;
ptr=ptr->right;
subL->right=ptr->left;
ptr->left=subL;
ptr->bf=subL->bf=0;
}
void LL(Node* &ptr){ //右单旋转
Node* subR=ptr;
ptr=ptr->left;
subR->left=ptr->right;
ptr->right=subR;
ptr->bf=subR->bf=0;
}
void LR(Node* &ptr){ //先左后右双旋转
Node *subR=ptr, *subL=ptr->left;
ptr=ptr->left->right;
subL->right=ptr->left;
ptr->left=subL;
if(ptr->bf==-1||ptr->bf==0) subL->bf=0; //ptr->bf值可能为-1或0
else subL->bf=-1;
subR->left=ptr->right;
ptr->right=subR;
if(ptr->bf==-1) subR->bf=1;
else subR->bf=0;
ptr->bf=0;
}
void RL(Node* &ptr){ //先右后左双旋转
Node *subL=ptr,*subR=ptr->right;
ptr=ptr->right->left;
subR->left=ptr->right;
ptr->right=subR;
if(ptr->bf==1||ptr->bf==0) subR->bf=0; //ptr->bf值可能为1或0
else subR->bf=1;
subL->right=ptr->left;
ptr->left=subL;
if(ptr->bf==1) subL->bf=-1;
else subL->bf=0;
ptr->bf=0;
}
bool Insert(Node* &ptr,int el){
Node *pre=NULL, *p=ptr, *ppre; //ptr指针记录根节点
stack<Node*> st;
while(p!=NULL){
if(el==p->data) return false;
pre=p;
st.push(pre);
if(el<p->data) p=p->left;
else p=p->right;
}
p=new Node();
p->data=el;
if(pre==NULL){
ptr=p;
return true;
}
if(el<pre->data) pre->left=p;
else pre->right=p;
while(!st.empty()){
pre=st.top();
st.pop();
if(p==pre->left) pre->bf--; //平衡因子的更新
else pre->bf++; //平衡因子的更新
if(pre->bf==0) break;
if(pre->bf==1||pre->bf==-1) p=pre;
else{
if(pre->bf*p->bf>0){ //同号,单旋转
if(pre->bf==-2) LL(pre);
else RR(pre);
}else{ //异号,双旋转
if(pre->bf==-2) LR(pre);
else RL(pre);
}
break;
}
}
if(st.empty()){
ptr=pre;
}else{
ppre=st.top();
if(pre->data<ppre->data) ppre->left=pre;
else ppre->right=pre;
}
return true;
}
bool Remove(Node* &ptr,int x)
{
Node *pre=NULL, *p=ptr, *temp, *ppre;
stack<Node*> st;
while(p!=NULL) //寻找删除位置
{
if(x==p->data) break; //找到等于x的结点p,停止搜索
pre=p;
st.push(pre); //否则用栈记忆查找路径
if(x<p->data) p=p->left;
else p=p->right;
}
if(p==NULL) return false; //未找到被删除结点,删除失败
if(p->left!=NULL&&p->right!=NULL) //被删除结点有两个子女
{
pre=p;
st.push(pre);
temp=p->left; //在p左子树找p的直接前驱
while(temp->right!=NULL)
{
pre=temp;
st.push(pre);
temp=temp->right;
}
p->data=temp->data; //用temp的值填补p
p=temp; //被删结点转化为temp,使p指向temp
}
if(p->left!=NULL) temp=p->left; //被删结点p只有一个子女q
else temp=p->right;
if(pre==NULL) ptr=temp; //被删结点为根节点,当真正删除的结点为根结点时,那表明这个树就这一个结点,ptr=NULL
else //被删结点不是根结点
{
if(pre->left==p) pre->left=temp; //连接,此后temp完成删除后子女链接的使命
else pre->right=temp;
while(!st.empty()) //重新平衡化
{
pre=st.top();
st.pop(); //从栈中退出父结点
if(pre->right==temp) pre->bf--; //调整父结点的平衡因子
else pre->bf++;
if(pre->bf==0) temp=pre; // |bf|=0
if(pre->bf==1||pre->bf==-1) break; // |bf|=1
if(pre->bf==2||pre->bf==-2) // |bf|=2
{
if(pre->bf=-2) temp=pre->left; //用temp指向较高的子树
else temp=pre->right; //用temp指向较高的子树
if(temp->bf==0)
{
if(pre->bf=-2)
{
LL(pre); //右单旋转,但把pre->bf=pre->left->bf=0了,下面需要值重置
pre->bf=1;
pre->left->bf=-1;
}
else
{
RR(pre); //左单旋转,但把pre->bf=pre->left->bf=0了,下面需要值重置
pre->bf=-1;
pre->right->bf=1;
}
break;
}
if(temp->bf * pre->bf > 0) //两结点平衡因子同号
{
if(pre->bf==-2) LL(pre); //右单旋转
else RR(pre); //左单旋转
}
else //两结点平衡因子反号
{
if(pre->bf==-2) LR(pre); //先左后右双旋转, " < "型
else RL(pre); //先右后左双旋转," > "型
}
}
}
if(st.empty()) { //旋转后与上层链接
ptr=pre;
}else{
ppre=st.top();
if(pre->data<ppre->data) ppre->left=pre;
else ppre->right=pre;
}
}
delete p;
return true;
}
void LevelTraversal(Node* ptr){
queue<Node*> Q;
Node* p=NULL;
Q.push(ptr);
while(!Q.empty()){
p=Q.front();
cout<<p->data<<" "<<p->bf<<endl;
Q.pop();
if(p->left!=NULL){
Q.push(p->left);
}
if(p->right!=NULL){
Q.push(p->right);
}
}
}
int main(){
Node* root=NULL;
int arr[]={16,3,7,11,9,26,18,14,15};
for(int i=0;i<sizeof(arr)/sizeof(int);i++){
Insert(root,arr[i]);
}
LevelTraversal(root);//结果应为:11 7 18 3 9 15 26 14 16
cout<<endl;
Remove(root,16);
LevelTraversal(root);
cout<<endl;
return 0;
}
//11 1
//7 0
//18 -1
//3 0
//9 0
//15 0
//26 0
//14 0
//16 0
//
//11 1
//7 0
//18 -1
//3 0
//9 0
//15 -1
//26 0
//14 0