//.......................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 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();
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树的插入删除操作
最新推荐文章于 2022-03-11 16:30:15 发布