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

来源:互联网 发布:删除表 sql drop 编辑:程序博客网 时间:2024/06/08 21:55

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

#ifndef AVL_DEC_H#define AVL_DEC_Htemplate <typename T>class AvlTree;int Max(int a1, int a2){    return a1 > a2 ? a1 : a2;}//节点类模板template<typename T>class Node{public:    friend class AvlTree<T>;    Node(T x);private:    T element;    Node<T> *left;    Node<T> *right;    int height;};//AVL树template <typename 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_Htemplate<typename T>Node<T>::Node(T x){    element = x;    left = nullptr;    right = nullptr;    height = 0;}template<typename T>AvlTree<T>::AvlTree(){    root = nullptr;}template<typename T>inline AvlTree<T>::~AvlTree(){    clear();}template<typename T>void AvlTree<T>::append(T x){    //调用另一个重载函数    root = append(x, root);}template <typename T>Node<T>* AvlTree<T>::append(T x, Node<T>* r){    if (r == nullptr)    {        r = new Node<T>(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<T>::Height(Node<T> * r){    if (r == nullptr)        return -1;    else        return r->height;}//清除元素template<typename T>void AvlTree<T>::clear(){    FreeTree(root);    root = nullptr;}template<typename T>void AvlTree<T>::FreeTree(Node<T>* 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<T>* AvlTree<T>::SingleRotationWithLeft(Node<T>* r){    Node<T>* 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<T>* AvlTree<T>::SingleRotationWithRight(Node<T>* r){    Node<T>* 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<T>* AvlTree<T>::DoubleRotationWithLeft(Node<T>* r){    r->left = SingleRotationWithRight(r->left);    return SingleRotationWithLeft(r);}template<typename T>Node<T>* AvlTree<T>::DoubleRotationWithRight(Node<T>* r){    r->right = SingleRotationWithLeft(r->right);    return SingleRotationWithRight(r);}//将树的所有元素输出到一个二维数组,安全性由调用例程负责template<typename T>void AvlTree<T>::Add2Array(Node<T>* 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 <iostream>#include "AVL.h"using namespace std;//打印元素template<typename T>inline void AvlTree<T>::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;}

这里写图片描述

原创粉丝点击