数据结构之AVL树

来源:互联网 发布:javascript笔试 编辑:程序博客网 时间:2024/05/16 00:47

   二叉排序树的查找与树的形态密切相关,当树的形态比较均衡时查找效率最高,当树的形态偏向于某一个方向是时效率迅速降低,当二叉排序树蜕变为单支树,树的深度为n时,其平均查找长度为(n+1)/2(和顺序查找相同)

1. 概述

AVL树是最早提出的自平衡二叉排序树,在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis。AVL树种查找、插入和删除在平均和最坏情况下都是O(log n),增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

2、插入时,四种情况可能导致AVL树不再平衡

   a、LL:插入一个新节点到节点的左子树(Left)的左子树(Left),可能导致节点左右子树的高度差为2

   b、LR:插入一个新节点到节点的左子树(Left)的右子树(Right),可能导致节点左右子树的高度差为2

   c、RR:插入一个新节点到节点的右子树(Right)的右子树(Right),可能导致节点左右子树的高度差为-2

   d、RL:插入一个新节点到节点的右子树(Right)的左子树(Left),可能导致节点左右子树的高度差为-2

3、删除时

   a、当删除节点右子树中的某个节点时,可能导致节点左右子树的高度差为2

   b、当删除节点左子树中的某个节点时,可能导致节点左右子树的高度差为-2

4、针对插入和删除引起的不平衡,都可以通过旋转来使之平衡,有四种旋转方式

   a、右旋转:节点旋转到节点右孩子的位置,节点左孩子旋转到节点的位置

   b、左旋转:节点旋转到节点左孩子的位置,节点右孩子旋转到节点的位置

   c、左右旋转:先左旋转,再右旋转

   d、右左旋转:先右旋转,再左旋转

(1)、对于LL情况,需右旋转,如下图所示:


(2)、对于RR情况,需左旋转,如下图所示:


(3)、对于LR情况需要左右旋转(先B左旋转,后A右旋转),如下图所示:


(4)、对于RL情况需要右左旋转(先B右旋转,后A左旋转,如下图所示:


5、AVL树的代码实现

   AVL树也是二叉排序树,操作方法基本相同,只是在插入和删除时,会引起AVL树不再平衡,需要通过旋转使之保持平衡。

#ifndef BINARYAvlTree#define BINARYAvlTreenamespace BinaryAvlTree{template<typename Element>class TreeNode{public:Element data;int high;//表示节点的高度,用来判断节点是否平衡TreeNode<Element> *lchild;TreeNode<Element> *rchild;TreeNode(Element data):data(data),lchild(NULL),rchild(NULL),high(1){};~TreeNode(){lchild = NULL;rchild = NULL;high = 1;};};template<typename Element>class AvlTree{private:TreeNode<Element> *root;int NodeNum;public:AvlTree(){root = NULL;NodeNum=0;};~AvlTree(){DestroyTree();};bool TreeIsEmpty();int TreeNodeNum(){return NodeNum;};bool InsertTreeNode(Element data);void InorderTravelTree();void SearchNode(Element data);bool RemoveNode(Element data);Element MaxValueOfTree();Element MinValueOfTree();int DepthOfTree();void DestroyTree();void InsertNode(TreeNode<Element> **t,TreeNode<Element> *node);void Inorder(TreeNode<Element> *t);TreeNode<Element>* Search(TreeNode<Element>* t, Element data, TreeNode<Element>**pre);void DestroyTree(TreeNode<Element>* t);int DepthOfTree(TreeNode<Element>* t);TreeNode<Element>* MaxValueOfTree(TreeNode<Element>* node,TreeNode<Element>** pre);        //=================AVL树新添加和==============================void RightRotate(TreeNode<Element>** t);//*t节点处的右旋转void LeftRotate(TreeNode<Element>** t);//*t节点处的左旋转void LeftRightRotate(TreeNode<Element>** t);//*t节点处的左右旋转void RightLeftRotate(TreeNode<Element>** t);//*t节点处的右左旋转void BalanceTree(TreeNode<Element>** t);//平衡以*t为根节点的树int Max(TreeNode<Element>* a,TreeNode<Element>* b);//返回节点a、b的最大高度int Balancefactor(TreeNode<Element>* a,TreeNode<Element>* b);//返回平衡因子,当为2或-2时,表示不平衡bool RemoveTreeNode(TreeNode<Element>** t,Element data);//查找data,并删除该节点void RemoveNode(TreeNode<Element>** t);//删除*t节点TreeNode<Element>* RemoveRightNode(TreeNode<Element>** t);//删除以*t为根节点的树的最右节点(最大值),并                                                          //返回该节点的地址//===========================================================};template <typename Element>//判断树是否为空bool AvlTree<Element>::TreeIsEmpty(){return root == NULL;}template <typename Element>int AvlTree<Element>::Max(TreeNode<Element>* a,TreeNode<Element>* b){if(a==NULL&&b==NULL)return 0;else if(a==NULL)return b->high;else if(b==NULL)return a->high;elsereturn a->high>b->high?a->high:b->high;}template <typename Element>int AvlTree<Element>::Balancefactor(TreeNode<Element>* a,TreeNode<Element>* b){if(a==NULL&&b==NULL)return 0;else if(a==NULL)return -(b->high);else if(b==NULL)return a->high;elsereturn a->high-b->high;}template <typename Element>//在二叉排序树中插入节点void AvlTree<Element>::InsertNode(TreeNode<Element> **t,TreeNode<Element> *node){if(node == NULL)return;if(*t==NULL)    //新插入的节点总为叶子节点*t = node;else{if(node->data<(*t)->data)//从节点的左孩子查找插入{InsertNode(&((*t)->lchild),node);(*t)->high = Max((*t)->lchild,(*t)->rchild)+1;//更新节点的高度if(Balancefactor((*t)->lchild,(*t)->rchild)==2)//左右孩子的高度差为2,需要重新平衡{/*如果节点插入到左孩子的左孩子,使用右旋转;否则使用左右旋转*/if(node->data<(*t)->lchild->data)RightRotate(t);elseLeftRightRotate(t);}}else{InsertNode(&((*t)->rchild),node);(*t)->high = Max((*t)->lchild,(*t)->rchild)+1;if(Balancefactor((*t)->rchild,(*t)->lchild)==2){if(node->data<(*t)->rchild->data)RightLeftRotate(t);elseLeftRotate(t);}}}}template <typename Element>bool AvlTree<Element>::InsertTreeNode(Element data){TreeNode<Element> *node = new TreeNode<Element>(data);if(node==NULL)return false;NodeNum++;InsertNode(&root,node);return true;}template <typename Element>//中序遍历二叉排序树,从小到大输出节点值void AvlTree<Element>::Inorder(TreeNode<Element> *t){if(t!=NULL){Inorder(t->lchild);cout<<t->data<<"("<<t->high<<")"<<" ";Inorder(t->rchild);}}template <typename Element>void AvlTree<Element>::InorderTravelTree(){Inorder(root);cout<<endl;}template <typename Element>//搜索二叉排序树,返回对应的节点,并取得节点的双亲节点TreeNode<Element>* AvlTree<Element>::Search(TreeNode<Element>* t, Element data, TreeNode<Element>**pre){if(pre != NULL)*pre = t;while(t!=NULL){if(t->data == data)return t;else if(t->data > data){if(pre != NULL)*pre = t;t = t->lchild;}else{if(pre != NULL)*pre = t;t = t->rchild;}}if(pre != NULL)*pre = NULL;return NULL;}template <typename Element>void AvlTree<Element>::SearchNode(Element data){TreeNode<Element> *pre;TreeNode<Element> *node;cout<<"================"<<endl;if(node=Search(root,data,&pre)){if(pre!=node)cout<<"The parent of "<<data<<" is: "<<pre->data<<endl;elsecout<<data<<" is root node"<<endl;if(node->lchild!=NULL)cout<<"The left child of "<<data<<" is: "<<node->lchild->data<<endl;elsecout<<"The left child of "<<data<<" is: NULL"<<endl;if(node->rchild!=NULL)cout<<"The right child of "<<data<<" is: "<<node->rchild->data<<endl;elsecout<<"The right child of "<<data<<" is: NULL"<<endl;}elsecout<<data<<" isn't in the tree"<<endl;cout<<"================"<<endl;}template <typename Element>bool AvlTree<Element>::RemoveNode(Element data){if(RemoveTreeNode(&root,data)){NodeNum--;return true;}return false;}template <typename Element>bool AvlTree<Element>::RemoveTreeNode(TreeNode<Element>** t,Element data){if((*t)==NULL)return false;if((*t)->data==data){RemoveNode(t);//删除找到的节点return true;}else{if(data<(*t)->data)//要删除的值小于当前节点的值,从节点的左孩子查找{bool tem = RemoveTreeNode(&((*t)->lchild),data);(*t)->high = Max((*t)->lchild,(*t)->rchild) + 1;//更新节点的高度if(Balancefactor((*t)->rchild,(*t)->lchild)==2)//如果右孩子的高度减左孩子的高度为2,需要重新平衡{/*如果右孩子的右孩子高度大于等于右孩子的左孩子高度,使用左旋转;否则使用右左旋转*/if(Balancefactor((*t)->rchild->rchild,(*t)->rchild->lchild)>=0)LeftRotate(t);elseRightLeftRotate(t);}return tem;}else{bool tem = RemoveTreeNode(&((*t)->rchild),data);(*t)->high = Max((*t)->lchild,(*t)->rchild) + 1;if(Balancefactor((*t)->lchild,(*t)->rchild)==2){if(Balancefactor((*t)->lchild->lchild,(*t)->lchild->rchild)>=0)RightRotate(t);elseLeftRightRotate(t);}return tem;}}}template <typename Element>void AvlTree<Element>::RemoveNode(TreeNode<Element>** t)//删除当前节点,分四种情况{if((t==NULL)||((*t)==NULL))return;else if((*t)->lchild==NULL){TreeNode<Element>* tem = *t;*t = (*t)->rchild;delete tem;}else if((*t)->rchild==NULL){TreeNode<Element>* tem = *t;*t = (*t)->lchild;delete tem;}else//如果左右孩子都不为空,用左孩子的最右节点(左孩子中的最大值)代替当前节点{TreeNode<Element>* tem = RemoveRightNode(&((*t)->lchild));(*t)->data = tem->data;(*t)->high = Max((*t)->lchild,(*t)->rchild) + 1;delete tem;}}template <typename Element>TreeNode<Element>* AvlTree<Element>::RemoveRightNode(TreeNode<Element>** t){if((t==NULL)||((*t)==NULL))return NULL;if((*t)->rchild==NULL){TreeNode<Element>* tem = *t;*t = (*t)->lchild;return tem;}else{TreeNode<Element>* tem = RemoveRightNode(&((*t)->rchild));(*t)->high = Max((*t)->lchild,(*t)->rchild) + 1;if(Balancefactor((*t)->lchild,(*t)->rchild)==2){if(Balancefactor((*t)->lchild->lchild,(*t)->lchild->rchild)>=0)RightRotate(t);elseLeftRightRotate(t);}return tem;}}template <typename Element>void AvlTree<Element>::BalanceTree(TreeNode<Element>** t){if((*t)!=NULL){BalanceTree(&(*t)->lchild);BalanceTree(&(*t)->rchild);(*t)->high = Max((*t)->lchild,(*t)->rchild) + 1;switch(Balancefactor((*t)->lchild,(*t)->rchild)){case 2:{if(Balancefactor((*t)->lchild->lchild,(*t)->lchild->rchild)>=0)RightRotate(t);elseLeftRightRotate(t);}case -2:{if(Balancefactor((*t)->rchild->rchild,(*t)->rchild->rchild)>=0)LeftRotate(t);elseRightLeftRotate(t);}}}}template <typename Element>TreeNode<Element>* AvlTree<Element>::MaxValueOfTree(TreeNode<Element>* node,TreeNode<Element>** pre){if(pre!=NULL)*pre = node;if(node==NULL)return NULL;while(node->rchild!=NULL){if(pre!=NULL)*pre = node;node = node->rchild;}return node;}template <typename Element>//返回树中最大值Element AvlTree<Element>::MaxValueOfTree(){if(root==NULL)return -1;TreeNode<Element> *node = root;while(node->rchild!=NULL)node = node->rchild;return node->data;}template <typename Element>//返回树中最小值Element AvlTree<Element>::MinValueOfTree(){if(root==NULL)return -1;TreeNode<Element> *node = root;while(node->lchild!=NULL)node = node->lchild;return node->data;}template <typename Element>//销毁树void AvlTree<Element>::DestroyTree(TreeNode<Element>*t){if(t!=NULL){DestroyTree(t->lchild);DestroyTree(t->rchild);delete t;}}template <typename Element>void AvlTree<Element>::DestroyTree(){DestroyTree(root);root=NULL;NodeNum = 0;}template <typename Element>//返回树的深度int AvlTree<Element>::DepthOfTree(TreeNode<Element>* t){if(t==NULL)return 0;int lh = DepthOfTree(t->lchild);int rh = DepthOfTree(t->rchild);return 1+(lh>rh?lh:rh);}template <typename Element>int AvlTree<Element>::DepthOfTree(){return DepthOfTree(root);}template <typename Element>void AvlTree<Element>::RightRotate(TreeNode<Element>** t){if((t==NULL)||(*t==NULL)||((*t)->lchild==NULL))return;TreeNode<Element>* head = *t;*t = (*t)->lchild;head->lchild = (*t)->rchild;(*t)->rchild = head;head->high = Max(head->lchild,head->rchild)+1;//更新旋转后的高度(*t)->high = Max((*t)->lchild,(*t)->rchild)+1;//更新旋转后的高度}template <typename Element>void AvlTree<Element>::LeftRotate(TreeNode<Element>** t){if((t==NULL)||(*t==NULL)||((*t)->rchild==NULL))return;TreeNode<Element>* head = *t;*t = (*t)->rchild;head->rchild = (*t)->lchild;(*t)->lchild = head;head->high = Max(head->lchild,head->rchild)+1;(*t)->high = Max((*t)->lchild,(*t)->rchild)+1;}template <typename Element>void AvlTree<Element>::LeftRightRotate(TreeNode<Element>** t){LeftRotate(&((*t)->lchild));RightRotate(t);}template <typename Element>void AvlTree<Element>::RightLeftRotate(TreeNode<Element>** t){RightRotate(&((*t)->rchild));LeftRotate(t);}}#endif


0 0