#pragma once
#include<stack>
#include<iostream>
using namespace std;
template<class Type>
class AVLTree;
template<class Type>
class AVLNode
{
friend class AVLTree<Type>;
public:
AVLNode() :data(0), leftChild(NULL), rightChild(NULL), bf(0)
{}
AVLNode(Type d) :data(d), leftChild(NULL), rightChild(NULL), bf(0)
{}
~AVLNode()
{}
private:
Type data;
int bf;
AVLNode<Type>*leftChild;
AVLNode<Type>*rightChild;
};
template<class Type>
class AVLTree
{
public:
AVLTree() :root(NULL)
{}
public:
bool Insert(Type &x)
{
return Insert(root, x);
}
bool Remove( Type x)
{
return Remove(root, x);
}
void sort()
{
sort(root);
}
protected:
void sort(AVLNode<Type>*t)const
{
if (t != NULL)
{
sort(t->leftChild);
cout << t->data << " ";
sort(t->rightChild);
}
}
bool Insert(AVLNode<Type>*&t, Type x)
{
AVLNode<Type> *p = t;
AVLNode<Type> *pr = NULL;//代表新增加节点的父节点
stack<AVLNode<Type>* >st;
while (p != NULL)//寻找插入位置,p为根
{
pr = p;
st.push(pr);
if (x < p->data)
p = p->leftChild;
else if (x > p->data)
p = p->rightChild;
else
return false;
}
p = new AVLNode<Type>(x);
if (pr == NULL)//空树,新节点为根节点(判断新节点有没有父节点
,即如果没有父节点,就为根节点)
{
t = p;
return true;
}
if (x < pr->data)
{
pr->leftChild = p;
}
else
{
pr->rightChild = p;
}
while (!st.empty())//比较难理解的是 p,pr 每次循环后与插入值之
间的关系,容易搞混(限于此循环)
{
pr = st.top();
st.pop();
if (p == pr->leftChild)
pr->bf--;
else
pr->bf++;
if (pr->bf == 0)
break;
else if (pr->bf == 1 || pr->bf == -1)
p = pr;
else
{
if (pr->bf > 0)
{
if (p->bf > 0)
{
RotateL(pr);
}
else
{
RotateRL(pr);
}
}
else
{
if (p->bf < 0)
{
RotateR(pr);
}
else
{
RotateLR(pr);
}
}
break;
}
}
if (st.empty())
{
t = pr;
}
else
{
AVLNode<Type>*q = st.top();
if (pr->data < q->data)
q->leftChild = pr;
else
q->rightChild = pr;
}
}
bool Remove(AVLNode<Type>*&t, Type &x)//p为要删除的节点
{
AVLNode<Type>*p = t;
AVLNode<Type>*pr = NULL;
stack<AVLNode<Type>*> st;
while (p != NULL)//找到要删除的节点p
{
if (x == p->data)
break;
pr = p;
st.push(pr);
if (x > p->data)
p = p->rightChild;
else
p = p->leftChild;
}
if (p == NULL)//被删节点不存在
return false;
AVLNode<Type>*q = NULL;
if (p->leftChild != NULL&&p->rightChild != NULL)//被删节点有
两个子女,最终转换为只有一个子女
{
pr = p;
st.push(pr);
q = p->leftChild;;//中序遍历的前驱(左子树中找最小的
)
while (q->rightChild != NULL)
{
pr = q;
st.push(pr);
q = q->rightChild;
}
p->data = q->data;//用q的值填补p 发现一个秘密:循环
完后栈的元素为3个,比如依次入栈的元素为11,18,15,执行完这句后栈的元素更改,
更改的元素为18,栈的元素为11,16,15,入栈之后也可以通过指针更改栈的元素,在
最后连接时,使用的出栈元素为更新值
p = q;//p永远是要删除的节点
}
if (p->leftChild != NULL)//1.转换的要删除节点已找到,要将将这
个删除节点转换,即判断这个要删除的节点有没有左右孩子( q指向p左子树代替或右子
树代替,删除p)
q = p->leftChild;
else
q = p->rightChild;
if (pr == NULL)//被删除节点为根节点
t = q;
else
{
if (pr->leftChild == p)//2.p(转化的要删节点)的父要重
新连接,即删除节点的父与删除节点的左孩子或者右孩子连接
pr->leftChild = q;
else
pr->rightChild = q;
/
//bf(调整平衡因子)
while (!st.empty())
{
pr = st.top();
st.pop();
if (pr->leftChild == q&&q != NULL)
pr->bf++;
else if ((pr->rightChild == q&&q != NULL) ||
q == NULL)
pr->bf--;
if (pr->bf == 1 || pr->bf == -1)
break;
else if (pr->bf == 0)//重新回溯
q = pr;
else//较矮子树被缩短
{
//q指向较高子树的根
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//q->bf和pr->bf相同或相反
{
if (q->bf<0 && pr->bf<0)
{
RotateR(pr);
}
else if (q->bf>0 && pr->bf>0)
{
RotateL(pr);
}
else if (q->bf<0 && pr->bf>0)
{
RotateRL(pr);
}
else if (q->bf>0 && pr->bf<0)
{
RotateLR(pr);
}
}
break;
}
}
if (st.empty())//调整新根
t = pr;
else//链接调整后的
{
AVLNode<Type> *tmp = st.top();
if (tmp->data > pr->data)
tmp->leftChild = pr;
else
tmp->rightChild = pr;
}
}
delete p;//p为删除的节点
return true;
}
protected:
//ptr均指不平衡的节点,SUBR,SUBL均为调整后新根的右,左子树
void RotateL(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subL = ptr;
ptr = subL->rightChild;
subL->rightChild = ptr->leftChild;
ptr->leftChild = subL;
ptr->bf = subL->bf = 0;
}
void RotateR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subR = ptr;
ptr = subR->leftChild;
subR->leftChild = ptr->rightChild;
ptr->rightChild = subR;
ptr->bf = subR->bf = 0;
}
void RotateLR(AVLNode<Type> *&ptr)
{
AVLNode<Type> *subR = ptr;
AVLNode<Type> *subL = subR->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 = 1;
else
subR->bf = 0;
ptr->bf = 0;
}
void RotateRL(AVLNode<Type> *&ptr)
{
AVLNode<Type>*subL = ptr;
AVLNode<Type>*subR = subL->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 = -1;
else
subL->bf = 0;
ptr->bf = 0;
}
private:
AVLNode<Type>*root;
};
#include<iostream>
using namespace std;
void main()
{
int ar[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//int ar[] = {50,30,70,10,35,60,80,32,38};
//int ar[] = {10, 20};
int n = sizeof(ar) / sizeof(int);
AVLTree<int> avl;
for (int i = 0; i < n; ++i)
{
avl.Insert(ar[i]);
}
avl.sort();
cout << endl;
avl.Remove(18);
avl.sort();
return;
}