//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
原文:https://www.cnblogs.com/zzyf/p/13392459.html