AVL树的插入删除操作
2017-07-23 11:32
363 查看
//.......................avl.h #pragma once #include<iostream> #include<stack> using namespace std; //................................动态平衡树-----AVL树 template<class Type> class AVL; //结点类 template<class Type> class AVLNode { friend class AVL<Type>; public: AVLNode():data(Type()),leftChild(NULL),rightChild(NULL),bf(0) {} AVLNode(Type d,AVLNode<Type> *left=NULL,AVLNode<Type>*right=NULL) :data(d),leftChild(left),rightChild(right),bf(0) {} ~AVLNode() {} private: Type data; AVLNode *leftChild; AVLNode *rightChild; int bf; }; //AVL类 template<class Type> class AVL { public: AVL():root(NULL) {} ~AVL() {} public: bool Insert(const Type &x) { return Insert(root,x); } bool Remove(const Type &x) { return Remove(root,x); } protected: bool Insert(AVLNode<Type>*&rt,const Type &x); bool Remove(AVLNode<Type>*&t,const Type &x); AVLNode<Type>* RotateR(AVLNode<Type> *&ptr); AVLNode<Type>* RotateL(AVLNode<Type> *&ptr); AVLNode<Type>* RotateRL(AVLNode<Type> *&ptr); AVLNode<Type>* RotateLR(AVLNode<Type> *&ptr); private: AVLNode<Type> *root; }; /* 8 --k1 5 5 --k2 ---- 经过右旋转 2 8 2 7 7 */ template<class Type> AVLNode<Type>* AVL<Type>::RotateR (AVLNode<Type>*&ptr) { AVLNode<Type> *k1=ptr; ptr=k1->leftChild; k1->leftChild=ptr->rightChild; ptr->rightChild=k1; k1->bf=ptr->bf=0; return ptr; } /* 5 --k1 8 8 --k2 ---左旋转 5 10 7 10 7 */ template<class Type> AVLNode<Type>* AVL<Type>::RotateL(AVLNode<Type>*&ptr) { AVLNode<Type> *k1=ptr; ptr=k1->rightChild; k1->rightChild=ptr->leftChild; ptr->leftChild=k1; k1->bf=ptr->bf=0; return ptr; } /* //..........................RL 18 18 20 14 22 ---> 14 20 ---> 18 22 20 24 22 14 19 24 19 19 24 18不平衡,先对20 22做一次右单旋转,再对18 20做一次左单旋转 */ template<class Type> AVLNode<Type>* AVL<Type>::RotateRL(AVLNode<Type>*&ptr) { AVLNode 4000 <Type>*subL = ptr; AVLNode<Type> *subR = ptr->rightChild ; ptr = subR->leftChild ; //第一次单旋转 subR->leftChild = ptr->rightChild ; ptr->rightChild = subR; if(ptr->bf >= 0) subR->bf = 0; else subR->bf = 1; //第二次单旋转 subL->rightChild = ptr->leftChild ; ptr->leftChild = subL; if(ptr->bf <= 0) subL->bf = 0; else subL->bf = -1; ptr->bf = 0; return ptr; } /* //.............LR 18 18 16 14 20 ---> 16 20 ---->14 18 12 16 14 12 15 20 15 12 15 18 不平衡 18 14 16 需要双旋转,先对14 16做一次单旋转(左旋转),再对16 18做一次单旋转(右旋转) */ template<class Type> AVLNode<Type>* AVL<Type>::RotateLR(AVLNode<Type>*&ptr) //双旋转 先左后右 { AVLNode<Type> *subR=ptr; AVLNode<Type> *subL=ptr->leftChild ; ptr=subL->rightChild ; //第一次单旋转 subL->rightChild =ptr->leftChild ; ptr->leftChild =subL; if(ptr->bf <=0) subL->bf =0; else subL->bf =-1; //左子树高于右子树 //第二次单旋转 subR->leftChild =ptr->rightChild ; ptr->rightChild =subR; if(ptr->bf >=0) subR->bf =0; else subR->bf =1; ptr->bf =0; //根的平衡因子一定为0 return ptr; } //删除操作:两个过程:删除操作以及调节二叉树平衡 /* 1.删除的节点最多只有一个子女结点 2.删除的节点有左右子树,此时需要考虑父节点的平衡因子,若为1或-1,则不需要调整, 若bf = 0,此时t=pr,向上回溯,若为2或者-2,需要进行旋转调整平衡,此时需要根据父节点的平衡因子来决定如何旋转。 */ template<class Type> bool AVL<Type>::Remove (AVLNode<Type> *&t,const Type &x) { if(t == NULL) return false; AVLNode<Type> *p = t; AVLNode<Type> *q; AVLNode<Type> *pr = NULL; stack<AVLNode<Type> *> st; while(p != NULL) { if(p->data == x) break; pr = p; //父节点等于p st.push(pr); if(x< p->data) p = p->leftChild; else p = p->rightChild; } if(p == NULL) //未找到被删结点,删除失败 return false; //被删结点有两个子女 if(p->leftChild!=NULL && p->rightChild!=NULL) { pr = p; st.push(pr); q = p->leftChild; //pr是q的父节点 while(q->rightChild != NULL) { pr = q; q = q->rightChild; } p->data = q->data; //用q的值填补p p = q; //被删结点转化为q } //被删节点p只有一个子女结点 if(p->leftChild != NULL) q = p->leftChild; else q = p->rightChild; if(pr == NULL) //删除的是根节点 t = q; //根节点变为q else { if(pr->leftChild == p) pr->leftChild = q; else pr->rightChild = q; /////////////////////////////////// while(!st.empty()) { pr = st.top(); st.pop(); if(pr->leftChild == q) pr->bf++; else pr->bf--; if(pr->bf==1 || pr->bf==-1) break; else if(pr->bf == 0) q = pr; else { if(pr->bf > 0) q = pr->rightChild; else q = pr->leftChild; if(q->bf == 0) // 单旋转 { if(pr->bf > 0) { RotateL(pr); pr->bf = -1; pr->leftChild ->bf = 1; } else { RotateR(pr); pr->bf = -1; pr->rightChild ->bf = 1; } } else if(q->bf > 0) { if(pr->bf > 0) // \ { RotateL(pr); } else // < { RotateLR(pr); } } else { if(pr->bf < 0) // / { RotateR(pr); } else // > { RotateRL(pr); } } break; } } AVLNode<Type> *ppr = st.top(); cf2b if(ppr->data > pr->data ) ppr->leftChild = pr; else ppr->rightChild = pr; } delete p; return true; } //Insert:两个过程:插入数据以及调节平衡 template<class Type> bool AVL<Type>::Insert(AVLNode<Type>*&rt, const Type &x) { AVLNode<Type> *pr = NULL; AVLNode<Type> *t = rt; //使p指向根节点 stack<AVLNode<Type>*> st; while(t != NULL) //当节点不为空时 { if(x == t->data ) return false; pr = t; st.push(pr); //将父节点压栈 if(x < t->data) //如果x小于节点的值,就在节点的左子树中插入x 根据二叉排序树进行插入 t= t->leftChild ; else t = t->rightChild; //否则,就在节点的右子树中插入x } t= new AVLNode<Type>(x); //如果节点为空,就在此节点处加入x信息 if(rt == NULL) //如果父节点为空,即是颗空树 { rt = t; //为根结点 return true; } if(x < pr->data) //父节点的左树插入 pr->leftChild = t; else pr->rightChild = t; //当栈不平衡时,调整平衡因子 while(!st.empty()) //当栈不空时 { pr = st.top(); st.pop(); //重新出到父节点 if(t == pr->leftChild) pr->bf--; //左树,平衡因子-1 else pr->bf++; if(pr->bf == 0) //判断父节点的平衡因子 break; //已经平衡 不用再调 else if(pr->bf==-1 || pr->bf==1) { t = pr; //父节点向上追踪 } else //不平衡 { if(pr->bf < 0) // 父节点的平衡因子小于0 左树高 { if(t->bf < 0) // / 还需要判断子节点的平衡因子 { RotateR(pr); } else // < { RotateLR(pr); } } else { if(t->bf > 0) // \ { RotateL(pr); } else // > { RotateRL(pr); } } break; } } if(st.empty()) //如果栈不空, { rt=pr; } else { AVLNode<Type> *s = st.top(); //q指向栈顶 if(pr->data <s->data) s->leftChild =pr; else s->rightChild =pr; } return true; } //........................test.cpp #include"avl.h" void main() { int ar[] = {16,3,7,11,9,26,18,14,15}; int n = sizeof(ar) / sizeof(int); AVL<int> avl; for(int i=0; i<n; ++i) { avl.Insert(ar[i]); } avl.Remove(1); }
相关文章推荐
- AVL树的插入、删除、查找操作
- (转)AVL树的插入_删除操作
- avl树的插入操作和删除操作
- 数据结构-----AVL树的插入删除操作
- AVL树的插入_删除操作实现~
- AVL树的插入删除操作
- AVL树的旋转,插入,删除操作
- [C++]数据结构:平衡的二叉搜索树之AVL树的结构特点与基础插入删除操作
- AVL树的插入与删除操作
- 假设串S1 = "I come from Beijing",S2 = "Chongqing" ,Sub = "America". 利用串的基本操作,如果串的赋值、串的插入、串的删除、串的替换、对上面
- B_树的插入、删除操作
- 二查排序树的基本操作(插入,删除,找前驱与后继)
- C语言实现双链表基本操作(创建、查找、插入、删除)
- 数据结构的一些基本操作(在表L中插入第i个元素e. 操作成功返回OK,失败时返回ERROR,删除表L中第i个元素,结果用e返回. 操作成功返回OK,失败时返回ERROR)
- AVL树的插入删除查找算法实现和分析-2(树高度法)
- 栈的基本操作--插入,取栈顶元素,删除栈顶,清空栈
- 再论循环链表的插入和删除操作
- 单链表的创建,插入,删除等操作——精简版
- C#中操作xml文件(插入节点、修改、删除)
- Hibernate批处理操作优化 (批量插入、更新与删除)