AVL树的插入删除操作
来源:互联网 发布:软件调试什么意思 编辑:程序博客网 时间:2024/06/06 02:04
//.......................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<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 1518 不平衡 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(); 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);}
阅读全文
0 0
- AVL树的旋转,插入,删除操作
- AVL树的插入删除操作
- AVL树的插入与删除操作
- 数据结构-----AVL树的插入删除操作
- AVL树的插入、删除、查找操作
- AVL树的插入删除操作
- AVL的插入,删除操作
- avl树的插入操作和删除操作
- (转)AVL树的插入_删除操作
- AVL树的插入_删除操作实现~
- 二叉平衡树AVL插入删除操作的实现
- avl tree的插入删除操作代码
- AVL树的插入操作
- AVL树插入删除
- AVL树的插入删除分析
- AVL树的插入、删除、旋转
- AVL树的查找,插入,删除
- AVL树的插入与删除
- 自己的python 学习笔记
- (88)将系统属性输出到文件中Properties.list方法
- Eigen 库的配置
- EXCEL排序(sort结构体排序)
- 安装使用celery异步任务
- AVL树的插入删除操作
- XML解析之PULL解析
- YUV格式学习:YUV420P、YV12、NV12、NV21格式转换成RGB24
- 《数据结构学习与实验指导》5-2:字符串关键字的散列映射
- vue-cli脚手架安装教程2017
- 多进程拷贝文件
- Android studio 项目构建一|依赖
- LeetCode- 125. Valid Palindrome
- nyoj-32 组合数