#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;
}