数据结构 学习笔记 (Avl树 代码结构详解和实现)
二叉树的基本概念
假期实现了Avl树,也没有找到很多资料,大部分的情况都是在debug中发现的,怕不常用忘记了,写个笔记记录一下写代码的心路历程,踩了很多坑,代码水平也不是很好,仅仅是作为笔记使用。
二叉树是一种常用的数据结构,每个父节点拥有2个子节点,这两个子节点往往被称为左节点和右节点。
二叉搜索树是一种特殊的二叉树,它的特点是左节点小于父节点,右节点大于父节点。
Avl树也叫二叉平衡树,会在二叉树的某一链路过长时对它进行重新调整。
二叉树
二叉树可以看成是一个有穷节点的集合。
二叉树可以为空。
若不为空,则可看成是由根节点,左子树和右子树构成的。
百度百科:二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个结点最多只能有两棵子树,且有左右之分。
就像上面这个样子,每个父节点有两个子节点。
但想在树里找到某个元素的位置,就不得不把整个树遍历一遍,时间复杂度是O(n)
Avl树 类的C++代码
template <class T>
class AvlNode{
public:
T data;
AvlNode<T>* lNode;
AvlNode<T>* rNode;
int height;
void add_Node(T Data){
AvlNode<T>* pNode = new AvlNode<T>;
pNode->data = Data;
pNode->lNode = nullptr;
pNode->rNode = nullptr;
pNode->height = height + 1;
if(Data <= data){
lNode = pNode;
}
else{
rNode = pNode;
}
}
};
template <class T>
class AvlTree
{
private:
AvlNode<T>* rootNode;
int getHeightest(AvlNode<T>* tNode);
int checkHeight(AvlNode<T>* checkNode);
void RRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void LLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void LRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void RLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void checkBalance(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
public:
AvlTree();
~AvlTree();
void getRootNode(T data);
void addNewNode(T data);
void deleteNode(T data);
AvlNode<T>* findNode(T data);
T findMax();
T findMin();
void inOrderTravel_Stack();
void inOrderTravel_Queue();
};
二叉树的遍历方式
有三种,先序遍历,中序遍历,后序遍历
先序遍历
先序遍历的顺序是:
根节点=>左子树的先序遍历=>右子树的先序遍历
从描述中很容易发现,可以用递归的方式遍历二叉树,这种方式代码也会很简单,但递归时间和空间的占用比较大,而且调用栈可能会溢出。
可以使用队列(FIFO)来实现非递归先序遍历。
如图,
将根节点加入队列=>再依次将队列后端节点的左节点加入队列,直至左节点为空=>从队列前端开始弹出,直至弹出节点的右节点不为空=>将右节点作为新的根节点进行循环。
中序遍历
中序遍历的顺序是:
左子树中序遍历=>访问根节点=>右子树中序遍历
同理,用递归的方式代码会比较简洁,也可通过使用堆栈的方式进行中序遍历
将根节点压入栈内=>依次将栈顶的左节点压入栈内,直至左节点为空=>依次弹出栈顶元素,直至弹出节点右节点不为空=>将右节点压入栈,作为新的根节点进行循环。
非递归中序遍历实现(栈) C++ 代码
template <class T>
void AvlTree<T>::inOrderTravel_Stack(){
Stack<AvlNode<T>*> stack;
AvlNode<T>* pAvlNode = rootNode;
stack.push(pAvlNode);
while (!stack.isEmpty())
{
while (pAvlNode->lNode != nullptr)
{
stack.push(pAvlNode->lNode);
pAvlNode = pAvlNode->lNode;
}
while (!stack.isEmpty() && stack.top()->rNode == nullptr)
{
cout<<stack.pop()->data<<" ";
}
if(!stack.isEmpty()){
if(stack.top()->rNode != nullptr){
pAvlNode = stack.top()->rNode;
cout<<stack.pop()->data<<" ";
stack.push(pAvlNode);
}
else{
cout<<stack.pop()->data<<" ";
}
}
}
cout<<endl;
}
后序遍历
后序遍历左子树,后序遍历右子树,访问根节点。
二叉搜索树
二叉搜索树与二叉树的区别就在于二叉搜索树父节点大于左节点,小于右节点。
二叉搜索树添加新节点
添加新节点时,我是令左节点的值小于等于父节点
C++代码实现
template <class T>
void AvlTree<T>::addNewNode(T data){
if(rootNode == nullptr){
getRootNode(data);
}
else{
// 设置检验二叉树平衡的观察点
int obTimes = 0;
AvlNode<T>* obNode1 = nullptr;
AvlNode<T>* obNode2 = nullptr;
AvlNode<T>* obNode3 = nullptr;
// 插入新节点
AvlNode<T>* pNode = rootNode;
while(pNode->lNode != nullptr || pNode->rNode != nullptr){
obTimes++;
if(obTimes %3 == 1){
obNode1 = pNode;
}
else if(obTimes %3 == 2){
obNode2 = pNode;
}
else{
obNode3 = pNode;
}
if(data <= pNode->data){
if(pNode->lNode != nullptr){
pNode = pNode->lNode;
}
if(pNode->lNode == nullptr && pNode->rNode != nullptr){
break;
}
}
else if(data > pNode->data){
if(pNode->rNode != nullptr){
pNode = pNode->rNode;
}
if(pNode->rNode == nullptr && pNode->lNode != nullptr){
break;
}
}
else{
;;
}
}
pNode->add_Node(data);
/*
*** 之后为Avl树的自平衡检测
*/
// 先检验观察点
if(pNode->height >= 2){
if(obTimes % 3 == 1){
cout<<"check 1"<<endl;
checkBalance(obNode2, obNode1, obNode3);
}
else if(obTimes % 3 == 2){
cout<<"check 2"<<endl;
checkBalance(obNode3, obNode2, obNode1);
}
else{
cout<<"check 0"<<endl;
checkBalance(obNode1, obNode3, obNode2);
}
}
}
}
二叉搜索树删除节点
删除节点时需要注意,树中的节点可大体分为三类:
- 无子节点
- 仅有左节点或右节点
- 左右节点都有
对于这三类,删除时也需注意:
- 无子节点:直接删除就好
- 有一个子节点:删除节点后,用子节点代替节点
- 有两个子节点:删除节点后,用节点左子树的最大值或者右子树的最小值代替节点
例:
无子节点
直接删除就好
如图中的“4”,直接删除就好。
有一个节点
删除节点后,用子节点代替节点
将“2”删除后,用子节点“4”来替代
有两个子节点
删除节点后,用左子树的最大值或者右子树的最小值来代替节点。
可以用左子树的最大值或者右子树的最小值来代替。这样做有一个好处是无论是最大值还是最小值,他们都没有子节点。
评价
二叉搜索树类似与二分法,时间复杂度在理想条件下是O(log(N)),但当树为
时间复杂度就变成了O(N),所以出现了二叉平衡树,防止出现这种情况。
Avl树(二叉平衡树)
Avl树左右子树的层高差不能超过一,像上面举的那个例子,转化成Avl树就是下面这样
那这个树是怎么得到的呢,我复原一下过程
节点的插入顺序不变,5,7,10,12,14,15
当插入节点“10”的时候,节点“5”左右层高不满足条件了,所以需要进行旋转。
(这里7的右节点应该是10)
继续添加节点,当添加到节点“14”时,节点“10”又不满足条件了,继续旋转。
在添加完节点“15”时,发现节点“7”左右层高不满足了,继续旋转
上述的三次旋转,都有一个相同的特征:
- 第一次:节点“5”不平衡了,破坏平衡的是右子树的右节点“10”
- 第二次:节点“10”不平衡了,破坏平衡的是右子树的右节点“14”
- 第三次:节点“7”不平衡了,破坏平衡的是右子树的右节点“15”
因此,我们管这种旋转叫RR旋转
类似的,可推理出还有LL旋转,RL旋转,LR旋转
RR旋转
第一种旋转较为简单,直接将三个节点逆时针旋转就好
第二种旋转,将node1转上去,并将node2的右节点指向之前node1的左节点,node1的左节点指向node2
C++实现代码
template <class T>
void AvlTree<T>::RRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"RR Rotate"<<endl;
if(obNode2 == nullptr){
if(fatherNode != nullptr){
bool isLeft1 = fatherNode->lNode == obNode1;
if(isLeft1){
fatherNode->lNode = obNode1->rNode;
}
else{
fatherNode->rNode = obNode1->rNode;
}
}
obNode1->height++;
obNode1->rNode->lNode = obNode1;
obNode1->rNode->height--;
if(obNode1->lNode != nullptr){
obNode1->lNode->height++;
}
if(obNode1->rNode->rNode != nullptr){
obNode1->rNode->rNode->height--;
}
if(fatherNode == nullptr){
rootNode = obNode1->rNode;
}
obNode1->rNode = nullptr;
}
else{
if(fatherNode != nullptr)
{
bool isLeft2 = fatherNode->lNode == obNode2;
if(isLeft2){
fatherNode->lNode = obNode1;
}
else{
fatherNode->rNode = obNode1;
}
}
obNode2->height++;
obNode1->height--;
obNode1->rNode->height--;
obNode1->rNode->rNode->height--;
obNode2->rNode = obNode1->lNode;
obNode2->lNode->height++;
obNode1->lNode = obNode2;
if(fatherNode == nullptr){
rootNode = obNode1;
}
}
}
代码中还出现了两种情况
这两种情况在单纯的需要RR旋转中是不会出现的,但在RL旋转中,先进行LL旋转后会出现这种情况。
LL旋转
LL旋转是RR旋转的镜像问题,就不解释了,直接附代码
C++代码
template <class T>
void AvlTree<T>::LLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"LL Rotate"<<endl;
if(obNode2 == nullptr){
if(fatherNode != nullptr){
bool isLeft1 = fatherNode->lNode == obNode1;
if(isLeft1){
fatherNode->lNode = obNode1->lNode;
}
else{
fatherNode->rNode = obNode1->lNode;
}
}
obNode1->height++;
obNode1->lNode->rNode = obNode1;
obNode1->lNode->height--;
if(obNode1->rNode != nullptr){
obNode1->rNode->height++;
}
if(obNode1->lNode->lNode != nullptr){
obNode1->lNode->lNode->height--;
}
if(fatherNode ==nullptr){
rootNode = obNode1->lNode;
}
obNode1->lNode = nullptr;
}
else{
if(fatherNode != nullptr)
{
bool isLeft2 = fatherNode->lNode == obNode2;
if(isLeft2){
fatherNode->lNode = obNode1;
}
else{
fatherNode->rNode = obNode1;
}
}
obNode2->height++;
obNode1->height--;
obNode1->lNode->height--;
obNode1->lNode->lNode->height--;
obNode2->lNode = obNode1->rNode;
obNode2->rNode->height++;
obNode1->rNode = obNode2;
if(fatherNode == nullptr){
rootNode = obNode1;
}
}
}
RL旋转
RL旋转就是先进行一个LL旋转,再进行一个RR旋转,只是不同情况的参数和写法会不同
具体情况有以下四种:
第一种
第二种
第三种
第四种
可以看到,第三种和第四种都可以通过一次RR旋转或者LL旋转变成第二种情况
c++代码
template <class T>
void AvlTree<T>::LRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"LR Rotate"<<endl;
if(obNode2 == nullptr){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(fatherNode, obNode1, nullptr);
}
else{
int check = checkHeight(obNode1);
if(check == 12){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(obNode2, obNode1, nullptr);
}
else if(check == 21){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(fatherNode, obNode1, obNode2);
}
else if(check == 19){
RRRotate(obNode2, obNode1, nullptr);
LLRotate(fatherNode, obNode2->lNode, obNode2);
}
else{
cout<<"LR error"<<endl;
}
}
}
LR旋转
与RL旋转类似,直接附代码了
C++代码
template <class T>
void AvlTree<T>::RLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"RL Rotate"<<endl;
if(obNode2 == nullptr){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(fatherNode, obNode1, nullptr);
}
else{
int check = checkHeight(obNode1);
if(check == 8){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(obNode2, obNode1, nullptr);
}
else if(check == 19){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(fatherNode, obNode1, obNode2);
}
else if(check == 21){
LLRotate(obNode2, obNode1, nullptr);
RRRotate(fatherNode, obNode2->rNode, obNode2);
}
else{
cout<<"LR error"<<endl;
}
}
}
自平衡的实现
整体自平衡的实现是在每次添加节点时进行检测。
写这篇文章的时候发现删除节点也会产生不平衡,但已经开学了,闲了去填这个坑吧,记录一下
不知道别人怎么实现的,因为时间问题也没有去差别人的实现方法
我用了三个观察点,分别记录新添加点的上上个节点,上上上个节点,上上上上个节点,在不同的旋转方式中会用到不同的节点,情况也比较好推,对着上面枚举的情况去一一找条件就好。
C++代码
template <class T>
void AvlTree<T>::checkBalance(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
int check1 = checkHeight(obNode1);
if(check1 < 15){
if((check1-10) >= 2){
if(obNode1->lNode->lNode != nullptr){
LLRotate(obNode2, obNode1, nullptr);
}
else{
LRRotate(obNode2, obNode1, nullptr);
}
}
else{
if(obNode1->rNode->rNode != nullptr){
RRRotate(obNode2, obNode1, nullptr);
}
else{
RLRotate(obNode2, obNode1, nullptr);
}
}
}
else if(check1 > 15 && obNode1->height >=2 )
{
int check2 = checkHeight(obNode2);
if((check2-20) == 2){
if((check1-20) == 2){
LLRotate(fatherNode, obNode1, obNode2);
}
else{
LRRotate(fatherNode, obNode1, obNode2);
}
}
else if((check2-20) == -2){
if((check1-20) == -2){
RLRotate(fatherNode, obNode1, obNode2);
}
else{
RRRotate(fatherNode, obNode1, obNode2);
}
}
}
}
完整代码
Avl.h
#include "Stack.h"
#include "Queue.h"
#include <iostream>
using namespace std;
template <class T>
class AvlNode{
public:
T data;
AvlNode<T>* lNode;
AvlNode<T>* rNode;
int height;
void add_Node(T Data){
AvlNode<T>* pNode = new AvlNode<T>;
pNode->data = Data;
pNode->lNode = nullptr;
pNode->rNode = nullptr;
pNode->height = height + 1;
if(Data <= data){
lNode = pNode;
}
else{
rNode = pNode;
}
}
};
template <class T>
class AvlTree
{
private:
AvlNode<T>* rootNode;
int getHeightest(AvlNode<T>* tNode);
int checkHeight(AvlNode<T>* checkNode);
void RRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void LLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void LRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void RLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
void checkBalance(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2);
public:
AvlTree();
~AvlTree();
void getRootNode(T data);
void addNewNode(T data);
void deleteNode(T data);
AvlNode<T>* findNode(T data);
T findMax();
T findMin();
void inOrderTravel_Stack();
void inOrderTravel_Queue();
};
template <class T>
AvlTree<T>::AvlTree(/* args */)
{
rootNode = nullptr;
}
template <class T>
AvlTree<T>::~AvlTree()
{
Queue<AvlNode<T>*> queue;
AvlNode<T>* pNode = rootNode;
queue.addNode(pNode);
while (!queue.isEmpty())
{
if(pNode->lNode != nullptr){
queue.addNode(pNode->lNode);
}
if(pNode->rNode != nullptr){
queue.addNode(pNode->rNode);
}
delete queue.deleteNode();
if(!queue.isEmpty()){
pNode = queue.front();
}
}
}
template <class T>
void AvlTree<T>::getRootNode(T data){
rootNode = new AvlNode<T>;
rootNode->data = data;
rootNode->lNode = nullptr;
rootNode->rNode = nullptr;
rootNode->height = 1;
}
template <class T>
void AvlTree<T>::addNewNode(T data){
if(rootNode == nullptr){
getRootNode(data);
}
else{
// 设置检验二叉树平衡的观察点
int obTimes = 0;
AvlNode<T>* obNode1 = nullptr;
AvlNode<T>* obNode2 = nullptr;
AvlNode<T>* obNode3 = nullptr;
// 插入新节点
AvlNode<T>* pNode = rootNode;
while(pNode->lNode != nullptr || pNode->rNode != nullptr){
obTimes++;
if(obTimes %3 == 1){
obNode1 = pNode;
}
else if(obTimes %3 == 2){
obNode2 = pNode;
}
else{
obNode3 = pNode;
}
if(data <= pNode->data){
if(pNode->lNode != nullptr){
pNode = pNode->lNode;
}
if(pNode->lNode == nullptr && pNode->rNode != nullptr){
break;
}
}
else if(data > pNode->data){
if(pNode->rNode != nullptr){
pNode = pNode->rNode;
}
if(pNode->rNode == nullptr && pNode->lNode != nullptr){
break;
}
}
else{
;;
}
}
pNode->add_Node(data);
// 先检验观察点
if(pNode->height >= 2){
if(obTimes % 3 == 1){
cout<<"check 1"<<endl;
checkBalance(obNode2, obNode1, obNode3);
}
else if(obTimes % 3 == 2){
cout<<"check 2"<<endl;
checkBalance(obNode3, obNode2, obNode1);
}
else{
cout<<"check 0"<<endl;
checkBalance(obNode1, obNode3, obNode2);
}
}
}
}
template <class T>
void AvlTree<T>::deleteNode(T data){
AvlNode<T>* pNode = rootNode;
AvlNode<T>* pNodeF;
// 找到被删节点的父节点
while (pNode->data != data)
{
pNodeF = pNode;
if(data <= pNode->data && pNode->lNode != nullptr){
pNode = pNode->lNode;
}
else if(data > pNode->data && pNode->rNode != nullptr){
pNode = pNode->rNode;
}
else{
cout<<"Error!. Can't delete a non-exixtent element"<<endl;
break;
}
}
pNode = pNodeF;
int isLeft = pNode->lNode != nullptr && pNode->lNode->data == data;
AvlNode<T>* deleteNode = isLeft ? pNode->lNode : pNode->rNode;
int childNum = 0;
if(deleteNode->lNode != nullptr){
childNum++;
}
if(deleteNode->rNode != nullptr){
childNum++;
}
AvlNode<T>* childNode;
AvlNode<T>* tempNode;
switch (childNum)
{
case 0:
if(isLeft){
pNode->lNode = nullptr;
}
else{
pNode->rNode = nullptr;
}
delete deleteNode;
break;
case 1:
childNode = pNode->lNode != nullptr ? pNode->lNode : pNode->rNode;
if(isLeft){
pNode->lNode = childNode;
}
else{
pNode->rNode = childNode;
}
childNode->height = deleteNode->height;
delete deleteNode;
break;
case 2:
if(isLeft){
tempNode = deleteNode->rNode;
while (tempNode->lNode != nullptr && tempNode->lNode->lNode != nullptr)
{
tempNode = tempNode->lNode;
}
if(tempNode->lNode == nullptr){
pNode->lNode = tempNode;
tempNode->lNode = deleteNode->lNode;
tempNode->rNode = nullptr;
}
else{
pNode->lNode = tempNode->lNode;
tempNode->lNode->lNode = deleteNode->lNode;
tempNode->lNode->rNode = deleteNode->rNode;
tempNode->lNode = nullptr;
}
pNode->lNode->height = deleteNode->height;
}
else{
tempNode = deleteNode->lNode;
while (tempNode->rNode != nullptr && tempNode->rNode->rNode != nullptr)
{
tempNode = tempNode->rNode;
}
if(tempNode->rNode == nullptr){
pNode->rNode = tempNode;
tempNode->rNode = deleteNode->rNode;
tempNode->lNode = nullptr;
}
else{
pNode->rNode = tempNode->rNode;
tempNode->rNode->lNode = deleteNode->lNode;
tempNode->rNode->rNode = deleteNode->rNode;
tempNode->rNode = nullptr;
}
pNode->rNode->height = deleteNode->height;
}
delete deleteNode;
break;
default:
break;
}
}
template <class T>
AvlNode<T>* AvlTree<T>::findNode(T data){
AvlNode<T>* pNode = rootNode;
// 找到被删节点的父节点
while (pNode->data != data)
{
if(data <= pNode->data && pNode->lNode != nullptr){
pNode = pNode->lNode;
}
else if(data > pNode->data && pNode->rNode != nullptr){
pNode = pNode->rNode;
}
else{
cout<<"Error!. Can't find this element"<<endl;
break;
}
}
return pNode;
}
template <class T>
T AvlTree<T>::findMax(){
AvlNode<T>* pNode = rootNode;
while (pNode->rNode != nullptr)
{
pNode = pNode->rNode;
}
return pNode->data;
}
template <class T>
T AvlTree<T>::findMin(){
AvlNode<T>* pNode = rootNode;
while (pNode->lNode != nullptr)
{
pNode = pNode->lNode;
}
return pNode->data;
}
template <class T>
void AvlTree<T>::inOrderTravel_Stack(){
Stack<AvlNode<T>*> stack;
AvlNode<T>* pAvlNode = rootNode;
stack.push(pAvlNode);
while (!stack.isEmpty())
{
while (pAvlNode->lNode != nullptr)
{
stack.push(pAvlNode->lNode);
pAvlNode = pAvlNode->lNode;
}
while (!stack.isEmpty() && stack.top()->rNode == nullptr)
{
cout<<stack.pop()->data<<" ";
}
if(!stack.isEmpty()){
if(stack.top()->rNode != nullptr){
pAvlNode = stack.top()->rNode;
cout<<stack.pop()->data<<" ";
stack.push(pAvlNode);
}
else{
cout<<stack.pop()->data<<" ";
}
}
}
cout<<endl;
}
template <class T>
int AvlTree<T>::getHeightest(AvlNode<T>* tNode){
int height = 0;
Stack<AvlNode<T>*> stack;
AvlNode<T>* pNode = tNode;
stack.push(pNode);
while (!stack.isEmpty())
{
while (pNode->lNode != nullptr)
{
stack.push(pNode->lNode);
pNode = pNode->lNode;
}
while (!stack.isEmpty() && stack.top()->rNode == nullptr)
{
int temp = stack.pop()->height;
height = temp > height ? temp : height;
}
if(!stack.isEmpty()){
if(stack.top()->rNode != nullptr){
pNode = stack.top()->rNode;
int temp = stack.pop()->height;
height = temp > height ? temp : height;
stack.push(pNode);
}
else{
int temp = stack.pop()->height;
height = temp > height ? temp : height;
}
}
}
return height;
}
// 返回值 = 子节点数 * 10 + 左支最高值 - 右支最高值
template <class T>
int AvlTree<T>::checkHeight(AvlNode<T>* checkNode){
int answer = 0;
int height0 = checkNode->height;
if(checkNode->lNode != nullptr){
answer += 10;
answer = answer + getHeightest(checkNode->lNode) - height0;
}
if(checkNode->rNode != nullptr){
answer += 10;
answer = answer - getHeightest(checkNode->rNode) + height0;
}
return answer;
}
template <class T>
void AvlTree<T>::RRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"RR Rotate"<<endl;
if(obNode2 == nullptr){
if(fatherNode != nullptr){
bool isLeft1 = fatherNode->lNode == obNode1;
if(isLeft1){
fatherNode->lNode = obNode1->rNode;
}
else{
fatherNode->rNode = obNode1->rNode;
}
}
obNode1->height++;
obNode1->rNode->lNode = obNode1;
obNode1->rNode->height--;
if(obNode1->lNode != nullptr){
obNode1->lNode->height++;
}
if(obNode1->rNode->rNode != nullptr){
obNode1->rNode->rNode->height--;
}
if(fatherNode == nullptr){
rootNode = obNode1->rNode;
}
obNode1->rNode = nullptr;
}
else{
if(fatherNode != nullptr)
{
bool isLeft2 = fatherNode->lNode == obNode2;
if(isLeft2){
fatherNode->lNode = obNode1;
}
else{
fatherNode->rNode = obNode1;
}
}
obNode2->height++;
obNode1->height--;
obNode1->rNode->height--;
obNode1->rNode->rNode->height--;
obNode2->rNode = obNode1->lNode;
obNode2->lNode->height++;
obNode1->lNode = obNode2;
if(fatherNode == nullptr){
rootNode = obNode1;
}
}
}
template <class T>
void AvlTree<T>::LLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"LL Rotate"<<endl;
if(obNode2 == nullptr){
if(fatherNode != nullptr){
bool isLeft1 = fatherNode->lNode == obNode1;
if(isLeft1){
fatherNode->lNode = obNode1->lNode;
}
else{
fatherNode->rNode = obNode1->lNode;
}
}
obNode1->height++;
obNode1->lNode->rNode = obNode1;
obNode1->lNode->height--;
if(obNode1->rNode != nullptr){
obNode1->rNode->height++;
}
if(obNode1->lNode->lNode != nullptr){
obNode1->lNode->lNode->height--;
}
if(fatherNode ==nullptr){
rootNode = obNode1->lNode;
}
obNode1->lNode = nullptr;
}
else{
if(fatherNode != nullptr)
{
bool isLeft2 = fatherNode->lNode == obNode2;
if(isLeft2){
fatherNode->lNode = obNode1;
}
else{
fatherNode->rNode = obNode1;
}
}
obNode2->height++;
obNode1->height--;
obNode1->lNode->height--;
obNode1->lNode->lNode->height--;
obNode2->lNode = obNode1->rNode;
obNode2->rNode->height++;
obNode1->rNode = obNode2;
if(fatherNode == nullptr){
rootNode = obNode1;
}
}
}
template <class T>
void AvlTree<T>::LRRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"LR Rotate"<<endl;
if(obNode2 == nullptr){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(fatherNode, obNode1, nullptr);
}
else{
int check = checkHeight(obNode1);
if(check == 12){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(obNode2, obNode1, nullptr);
}
else if(check == 21){
RRRotate(obNode1, obNode1->lNode, nullptr);
LLRotate(fatherNode, obNode1, obNode2);
}
else if(check == 19){
RRRotate(obNode2, obNode1, nullptr);
LLRotate(fatherNode, obNode2->lNode, obNode2);
}
else{
cout<<"LR error"<<endl;
}
}
}
template <class T>
void AvlTree<T>::RLRotate(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
cout<<"RL Rotate"<<endl;
if(obNode2 == nullptr){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(fatherNode, obNode1, nullptr);
}
else{
int check = checkHeight(obNode1);
if(check == 8){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(obNode2, obNode1, nullptr);
}
else if(check == 19){
LLRotate(obNode1, obNode1->rNode, nullptr);
RRRotate(fatherNode, obNode1, obNode2);
}
else if(check == 21){
LLRotate(obNode2, obNode1, nullptr);
RRRotate(fatherNode, obNode2->rNode, obNode2);
}
else{
cout<<"LR error"<<endl;
}
}
}
template <class T>
void AvlTree<T>::checkBalance(AvlNode<T>* fatherNode, AvlNode<T>* obNode1, AvlNode<T>* obNode2){
int check1 = checkHeight(obNode1);
if(check1 < 15){
if((check1-10) >= 2){
if(obNode1->lNode->lNode != nullptr){
LLRotate(obNode2, obNode1, nullptr);
}
else{
LRRotate(obNode2, obNode1, nullptr);
}
}
else{
if(obNode1->rNode->rNode != nullptr){
RRRotate(obNode2, obNode1, nullptr);
}
else{
RLRotate(obNode2, obNode1, nullptr);
}
}
}
else if(check1 > 15 && obNode1->height >=2 )
{
int check2 = checkHeight(obNode2);
if((check2-20) == 2){
if((check1-20) == 2){
LLRotate(fatherNode, obNode1, obNode2);
}
else{
LRRotate(fatherNode, obNode1, obNode2);
}
}
else if((check2-20) == -2){
if((check1-20) == -2){
RLRotate(fatherNode, obNode1, obNode2);
}
else{
RRRotate(fatherNode, obNode1, obNode2);
}
}
}
}
Queue.h
#define QUEUE_ERROR 404
template <class T>
class QueNode{
public:
T data;
QueNode* next;
};
template <class T>
class Queue
{
private:
QueNode<T>* frontNode;
QueNode<T>* rearNode;
public:
Queue(/* args */);
~Queue();
bool isEmpty();
void addNode(T data);
T deleteNode();
T front(){
if(isEmpty()){
return nullptr;
}
else{
return frontNode->next->data;
}
}
};
template <class T>
Queue<T>::Queue(/* args */)
{
frontNode = new QueNode<T>;
rearNode = new QueNode<T>;
frontNode->data = 0;
rearNode->data = 0;
frontNode->next = nullptr;
rearNode->next = nullptr;
}
template <class T>
Queue<T>::~Queue()
{
}
template <class T>
bool Queue<T>::isEmpty(){
if(frontNode->next == nullptr){
return true;
}
else{
return false;
}
}
template <class T>
void Queue<T>::addNode(T data){
if(frontNode->next == nullptr){
frontNode->next = rearNode;
rearNode->data = data;
rearNode->next = nullptr;
}
else{
rearNode->next = new QueNode<T>;
rearNode = rearNode->next;
rearNode->data = data;
rearNode->next = nullptr;
}
}
template <class T>
T Queue<T>::deleteNode(){
if(frontNode->next == nullptr){
delete frontNode;
return (T)QUEUE_ERROR;
}
else{
QueNode<T>* pNode = frontNode->next;
T temp = pNode->data;
frontNode->next = pNode->next;
delete pNode;
return temp;
}
}
Stack.h
#define STACK_ERROR 404
template <class T>
class StkNode{
public:
T data;
StkNode<T>* next;
};
template <class T>
class Stack{
private:
StkNode<T>* rootNode;
StkNode<T>* topNode;
public:
Stack();
~Stack();
bool isEmpty();
void push(T data);
T pop();
T top(){
if(isEmpty()){
return nullptr;
}
else{
return topNode->data;
}
}
};
template <class T>
Stack<T>::Stack(/* args */)
{
rootNode = new StkNode<T>;
topNode = new StkNode<T>;
rootNode->data = 0;
rootNode->next = nullptr;
topNode->data = 0;
topNode->next = rootNode;
}
template <class T>
Stack<T>::~Stack()
{
delete rootNode;
delete topNode;
}
template <class T>
bool Stack<T>::isEmpty(){
if(topNode->next == rootNode){
return true;
}
else{
return false;
}
}
template <class T>
void Stack<T>::push(T data){
StkNode<T>* pNode = new StkNode<T>;
pNode->data = data;
pNode->next = topNode;
topNode = pNode;
}
template <class T>
T Stack<T>::pop(){
if(topNode->next != rootNode){
StkNode<T>* pNode = topNode;
T temp = pNode->data;
topNode = topNode->next;
delete pNode;
return temp;
}
else{
return (T)STACK_ERROR;
}
}