二叉树中全部结点的平衡因子BF
的绝对值均小于等于1
,即:\(|BF|\leq1\)。平衡因子是,结点的左子树高度减去右子树的高度。平衡因子BF
绝对值大于1
表示二叉树失衡。ios
两种状况:c++
1
,向该结点的左子树插入结点,该结点的平衡因子变为2
,致使失衡;-1
,向该结点的右子树插入结点,该结点的平衡因子变为-2
,致使失衡。如何解决失衡?函数
关键问题是要找到失衡结点,离插入结点最近的失衡结点。this
失衡结点的特色:spa
解决办法:指针
采用递归的方法进行插入,插入成功后会进行回代,所以在回代的过程当中能够判断结点是否失衡,从而可以找到离插入结点最近的失衡结点。code
/* 一、判断二叉树是否失衡,若失衡返回true,不然返回false 二、若二叉树失衡,则返回离插入结点最近的结点 */ bool IsBalanced(BTNode<T> *&T,T key) { if(!T) { //未找到值为key的结点,进行插入 Insert(key); return true; } else if(T->data==key) { return false;//找到结点key,不可插入 } else if(T->data>key) { bool temp=IsBalanced(T->lchild,key);//若是temp为真,则表示结点插入到T的左子树 if(temp) { //判断T的平衡因子,若等于1,则须要调整 } } else { //同上 } }
附上完整代码:排序
#include <iostream> using namespace std; //结点结构 template <class T> class BTNode { public: //结点数据 T data; //左右孩子指针 BTNode<T> *lchild, *rchild; //添加平衡因子 int BF; public: //构造函数 BTNode(T D, int bf = 0, BTNode<T> *l = NULL, BTNode<T> *r = NULL) : data(D), BF(bf), lchild(l), rchild(r) {} }; //AVL平衡二叉树 template <class T> class AVLTree { //私有属性 private: //二叉树根节点 BTNode<T> *root; private: //销毁二叉树 void Destory(BTNode<T> *&rt) { if(rt) { this->Destory(rt->lchild); this->Destory(rt->rchild); delete rt; } } //二叉树查找 //和二叉排序树的查找方法同样 bool SearchAVL(BTNode<T> *rt, T key, BTNode<T> *&p, BTNode<T> *f = NULL) { if (!rt) //查找失败,返回false { p = f; //p指向查找路径上最后访问的元素 return false; } else if (rt->data == key) //查找成功,返回true { p = rt; //p指向查找到的元素 return true; } else if (rt->data > key) { return this->SearchAVL(rt->lchild, key, p, rt); } else { return this->SearchAVL(rt->rchild, key, p, rt); } } //左旋处理 void L_Rotate(BTNode<T> *&p) { BTNode<T> *R = p->rchild; //R指向p的左孩子 p->rchild = R->lchild; //p的右孩子指向R的左孩子 R->lchild = p; //R的左孩子指向p p = R; //该二叉树的根节点变为R } //右旋处理 void R_Rotate(BTNode<T> *&p) { BTNode<T> *L = p->lchild; p->lchild = L->rchild; L->rchild = p; p = L; } //左平衡处理,已知结点的平衡因子是+2,所以一定是在该结点的左子树插入的结点 //二叉排序树的根节点平衡因子的绝对值大于1,需进行平衡处理 void LeftBalance(BTNode<T> *&p) { BTNode<T> *L = p->lchild; //L指向p的左孩子 /* 判断L的平衡因子 若平衡因子为1,表示新节点插入在L的左子树 若平衡因子为-1,表示新节点插入在L的右子树 */ switch (L->BF) { case 1: //结点插入在L的左子树,需进行右旋处理 this->R_Rotate(p); p->BF = 0; p->rchild->BF = 0; //右旋处理后,需改变旋转结点的平衡因子 break; case -1: { //结点插入在L的右子树,需进行双旋处理 BTNode<T> *L_R = L->rchild; switch (L_R->BF) { case 1: //结点插入在L_R的左子树 p->BF = -1; L->BF = 0; break; case 0: //结点L_R就是新插入的结点 p->BF = 0; L->BF = 0; break; case -1: //结点插入在L_R的右子树 p->BF = 0; L->BF = 1; break; } L_R->BF = 0; this->L_Rotate(L); //先左旋处理 this->R_Rotate(p); //后右旋处理 break; } } } //右平衡处理,已知结点的平衡因子是-2,所以一定是在该结点的右子树插入的结点 void RightBalance(BTNode<T> *&p) { BTNode<T> *R = p->rchild; switch (R->BF) { case 1: { //新节点插入在R的左子树上,需进行双旋处理 BTNode<T> *R_L = R->lchild; switch (R_L->BF) { case 1: //结点插入在R_L的左子树上 p->BF = 0; R->BF = -1; break; case 0: //R_L就是新插入的结点 p->BF = 0; R->BF = 0; break; case -1: //结点插入在R_L的右子树上 p->BF = 1; R->BF = 0; break; } R_L->BF = 0; this->R_Rotate(R); //先右旋处理 this->L_Rotate(p); //后左旋处理 break; } case -1: //新节点插入在R的右子树上,需进行左旋处理 p->BF = 0; R->BF = 0; this->L_Rotate(p); break; } } //向二叉树中插入结点,并保持平衡 bool InsertAVL(BTNode<T> *&rt, T key, bool &taller) //taller用来记录二叉树是否长高 { if (!rt) //表示未在二叉树中找到结点值为key的结点,需插入结点 { rt = new BTNode<T>(key, 0, NULL, NULL); //将新节点赋值给rt指针 taller = true; return true; } else if (rt->data == key) //存在key,返回false { taller = false; return false; } else if (rt->data > key) { if (!this->InsertAVL(rt->lchild, key, taller)) //未插入结点 { return false; } if (taller) //二叉树长高,表示递归回到rt结点 { switch (rt->BF) { case 1: //结点rt的平衡因子为1,而又在左子树新插入结点,故结点rt失衡,需调整 this->LeftBalance(rt); taller = false; //维护状态,在失衡结点调整后,其祖父结点的平衡因子不会变,故不用更改,结束此模块递归 break; case 0: //结点rt的平衡因子为0,在左子树插入结点,结点rt不会失衡,不用调整 rt->BF = 1; taller = true; //插入新节点,二叉树高度增长,继续此模块递归,找到失衡结点 break; case -1: //结点rt的平衡因子为-1,在左子树插入结点,结点rt不会失衡,不用调整 rt->BF = 0; taller = false; //插入新节点,二叉树高度未增,结束此模块递归 break; } } return true; } else { if (!this->InsertAVL(rt->rchild, key, taller)) //未插入结点 { return false; } if (taller) //二叉树长高,表示递归回到rt结点 { switch (rt->BF) { case 1: //结点rt的平衡因子为1,而又在右子树新插入结点,故结点rt不会失衡 rt->BF = 0; taller = false; //插入新节点,二叉树高度未增,结束此模块递归 break; case 0: //结点rt的平衡因子为0,在右子树插入结点,结点rt不会失衡,不用调整 rt->BF = -1; taller = true; //插入新节点,二叉树高度增长,继续此模块递归,找到失衡结点 break; case -1: //结点rt的平衡因子为-1,在右子树插入结点,结点rt会失衡,用调整 this->RightBalance(rt); taller = false; //维护状态,在失衡结点调整后,其祖父结点的平衡因子不会变,故不用更改,结束此模块递归 break; } } return true; } } //前序遍历 void PreOrder(BTNode<T> *rt) { if (rt) { cout << rt->data << " "; this->PreOrder(rt->lchild); this->PreOrder(rt->rchild); } } //中序遍历 void InOrder(BTNode<T> *rt) { if(rt) { this->InOrder(rt->lchild); cout<<rt->data<<" "; this->InOrder(rt->rchild); } } public: //构造函数 AVLTree() : root(NULL) {} //拷贝构造函数 AVLTree(const AVLTree<T> &t) {} //销毁二叉树 void Destory() { this->Destory(this->root); this->root=NULL; } //析构函数 ~AVLTree() { this->Destory(this->root); } //前序遍历 void PreOrder() { this->PreOrder(this->root); } //中序遍历 void InOrder() { this->InOrder(this->root); } //二叉树查找 bool Search(T key, BTNode<T> *&p = NULL) { return this->SearchAVL(this->root, key, p, NULL); } //插入操做 bool Insert(T key) { bool p; return this->InsertAVL(this->root, key, p); } }; int main() { AVLTree<int> temp; for (int i = 0; i < 10; i++) { temp.Insert(i); } temp.PreOrder(); cout<<endl; temp.InOrder(); cout<<endl; system("pause"); return 0; }