二叉树 学习笔记 (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;
    }
}
    



  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值