平衡二叉查找(AVL)树(C++模板实现)

最近在学习《数据结构与算法分析(C语言描述)》,上面讲到一个带平衡条件的二叉查找树,之前在一家公司笔试也遇到了类似的题,于是决定自己用C++模板实现一遍。
(声明文件)AVL.h :

#ifndef AVL_DEC_H
#define AVL_DEC_H

template T>
class AvlTree;

int Max(int a1, int a2)
{
    return a1 > a2 ? a1 : a2;
}

//节点类模板
templateT>
class Node
{
public:
    friend class AvlTree<T>;
    Node(T x);
private:
    T element;
    Node<T> *left;
    Node<T> *right;
    int height;
};

//AVL树
template T>
class AvlTree
{
public:
    AvlTree();
    ~AvlTree();
    void append(T x);
    static int Height(Node<T>* tree);
    void print();
    void clear();
private:
    void FreeTree(Node<T>* r);
    Node<T>* append(T x, Node<T>* r);
    void Add2Array(Node<T>* r, T** a, int* b, int n);
    Node<T>* SingleRotationWithLeft(Node<T>*);
    Node<T>* SingleRotationWithRight(Node<T>*);
    Node<T>* DoubleRotationWithLeft(Node<T>*);
    Node<T>* DoubleRotationWithRight(Node<T>*);
private:
    Node<T>* root;
};

#include "AVL_def.h"

#endif // !AVL_DEC_H

(实现文件)AVL_def.h :

#ifndef AVL_DEF_H
#define AVL_DEF_H

template<typename T>
Node::Node(T x)
{
    element = x;
    left = nullptr;
    right = nullptr;
    height = 0;
}

template<typename T>
AvlTree::AvlTree()
{
    root = nullptr;
}

template<typename T>
inline AvlTree::~AvlTree()
{
    clear();
}

template<typename T>
void AvlTree::append(T x)
{
    //调用另一个重载函数
    root = append(x, root);
}

template <typename T>
Node* AvlTree::append(T x, Node* r)
{
    if (r == nullptr)
    {
        r = new Node(x);
    }
    else if (x < r->element)
    {
        //要插入的数比当前节点数小,向左递归
        r->left = append(x, r->left);

        //如果插入操作导致当前节点不平衡
        if (Height(r->left) - Height(r->right) == 2)
        {
            //在左儿子的左子树插入
            if (x < r->left->element)
                r = SingleRotationWithLeft(r);//进行一次从左向右的单旋转

            //在左儿子的右子树插入
            else
                r = DoubleRotationWithLeft(r);//进行一次从左向右的双旋转
        }
    }
    else if (x > r->element)
    {
        //要插入的数比当前节点数大,向右递归
        r->right = append(x, r->right);

        //如果插入操作导致当前节点不平衡
        if (Height(r->right) - Height(r->left) == 2)
        {
            //在右儿子的右子树插入
            if (x > r->right->element)
                r = SingleRotationWithRight(r);//进行一次从左向右的单旋转

            //在右儿子的左子树插入
            else
                r = DoubleRotationWithRight(r);//进行一次从左向右的双旋转
        }
    }
    r->height = Max(Height(r->left), Height(r->right)) + 1;
    return r;
}

//计算树的深度
template<typename T>
int AvlTree::Height(Node * r)
{
    if (r == nullptr)
        return -1;
    else
        return r->height;
}

//清除元素
template<typename T>
void AvlTree::clear()
{
    FreeTree(root);
    root = nullptr;
}

template<typename T>
void AvlTree::FreeTree(Node* r)
{
    if (r == nullptr)
        return;

    if (r->left == nullptr && r->right == nullptr)
        delete r;
    else
    {
        FreeTree(r->left);
        FreeTree(r->right);
        delete r;
    }
}

template<typename T>
Node* AvlTree::SingleRotationWithLeft(Node* r)
{
    Node* k1;
    k1 = r->left;
    r->left = k1->right;
    k1->right = r;
    r->height = Max(Height(r->left),
        Height(r->right)) + 1;
    k1->height = Max(Height(k1->left), r->height) + 1;
    return k1;
}

template<typename T>
Node* AvlTree::SingleRotationWithRight(Node* r)
{
    Node* k1;
    k1 = r->right;
    r->right = k1->left;
    k1->left = r;
    r->height = Max(Height(r->left),
        Height(r->right)) + 1;
    k1->height = Max(Height(k1->right), r->height) + 1;
    return k1;
}

template<typename T>
Node* AvlTree::DoubleRotationWithLeft(Node* r)
{
    r->left = SingleRotationWithRight(r->left);
    return SingleRotationWithLeft(r);
}

template<typename T>
Node* AvlTree::DoubleRotationWithRight(Node* r)
{
    r->right = SingleRotationWithLeft(r->right);
    return SingleRotationWithRight(r);
}

//将树的所有元素输出到一个二维数组,安全性由调用例程负责
template<typename T>
void AvlTree::Add2Array(Node* r, T** a, int* b, int n)
{
    if (r == nullptr)
        return;
    a[n][b[n]++] = r->element;

    Add2Array(r->left, a, b, n + 1);
    Add2Array(r->right, a, b, n + 1);
}
#endif // !AVL_DEF_H

(测试)main.cpp :

#include 
#include "AVL.h"

using namespace std;

//打印元素
template<typename T>
inline void AvlTree::print()
{
    int n = Height(root) + 1;
    T** a = new T*[n];
    int *b = new int[n];
    for (int i = 0; i < n; ++i)
    {
        a[i] = new T[pow(2, i)];
        b[i] = 0;
    }
    Add2Array(root, a, b, 0);

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n - i - 1; ++j)
            cout << "  ";
        for (int j = 0; j < b[i]; ++j)
        {
            cout << a[i][j] << "  ";
        }
        cout << endl;
    }

    for (int i = 0; i < n; ++i)
        delete[] a[i];
    delete[] a;
    delete[] b;
}

int main()
{
    int a[] = { 1,2,3,4,8,7,12,9,32,45,13,24,17 };
    AvlTree<int> avl;
    for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
        avl.append(a[i]);
    avl.print();
    system("pause");
    return 0;
}

平衡二叉查找(AVL)树(C++模板实现)_第1张图片

你可能感兴趣的:(数据结构)