找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3859|回复: 0

【C++】C++模板实现的AVL树

[复制链接]
发表于 2014-12-8 17:49:03 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
1 AVL树的定义
AVL树是一种自平衡二叉排序树,它的特点是任何一个节点的左子树高度和右子树的高度差在-1,0,1三者之间。AVL树的任何一个子树都是AVL树。
2 AVL树的实现
AVL树本质是一种二叉排序树,所以二叉排序树的任何性质AVL树都具有,但是AVL树稍微复杂的地方就是AVL树必须满足平衡条件,具体跟BST不同的地方主要体现在插入,删除操作。
插入操作:当插入之后可能会出现不平衡,所以这时候要通过旋转树来实现平衡。旋转有四种类型,左左,左右,右左,右右。其中左左旋转和右右旋转是镜像的,左右旋转和右左旋转是镜像的,所以实质上就是两种类型的旋转。针对左左旋转,只需要旋转一次即可,针对左右旋转,需要执行两次旋转。见下图:
1.png
这里采用递归法实现插入和删除操作。使用递归方便的一点是如果函数的参数是引用类型的,当传入一个p->left的时候,我们在当前函数的下层递归的时候,对p进行的赋值操作其实就是对上层递归中的p->left进行的操作,所以这样就不需要传递父指针了。
3 实现代码
AVLTree.h
//AVLTree.h
#ifndef DDXX_AVLTREE_H
#define DDXX_AVLTREE_H
#include <iostream>
#include <queue>
using namespace std;
template<typename Type>
class AVLTree
{
    struct Node
    {
        Type e;
        Node* left;
        Node* right;
        int h;
        Node(Type _e):e(_e),left(NULL),right(NULL),h(0){}
        Node(Type _e,Node* _left,Node* _right,int _h):e(e),left(_left),right(_right),h(_h){}
    };
public:
    AVLTree();
    AVLTree(Type arr[],int nLength);
    /*AVLTree(const AVLTree& right);
    AVLTree& operator=(const AVLTree& right);*/
    ~AVLTree();
public:
    bool    insert(Type e,Node* &p);
    void    erase(Type e,Node* &p);
    Node*&  find(Type e)const;
    void    traverse(Node* p)const;
    void    traverseByLevel(Node* p)const;
    int     getLength(){return mLength;}
    Node*&  getParent(Node* p);
    Node*&  getRoot(){return mRoot;} //notice the return type
    bool    empty(){return mRoot==NULL;};
    void    clear();
    void    clears(Node* &p);
private:
    void    rotateLeft(Node* &k2);
    void    rotateRight(Node* &k2);
    void    rotateLeftDouble(Node* &p);
    void    rotateRightDouble(Node* &p);
    int     height(Node* p)const{ return p == NULL ? -1 : p->h ;}
    int     max(int x,int y){return x>y?x:y;}
private:
    Node* mRoot;
    int mLength;

};
template<typename Type> AVLTree<Type>::AVLTree():mRoot(NULL),mLength(0)
{
}

template<typename Type> AVLTree<Type>::AVLTree(Type arr[],int nLength):mRoot(NULL),mLength(0)
{
    for(int i=0;i<nLength;i++)
    {
        insert(arr[i],mRoot);
    }
}

template<typename Type> AVLTree<Type>::~AVLTree()
{
    clears(mRoot);
}
template<typename Type> bool AVLTree<Type>::insert(Type e,Node* &p)
{
    if( p== NULL)
    {
        p = new Node(e);
        mLength++;
    }
    else if(e < p->e)
    {
        insert(e,p->left);
        if( height(p->left) - height(p->right) == 2)
        {
            if (e < p->left->e)
                rotateLeft(p);
            else
                rotateLeftDouble(p);
        }
    }
    else if(e > p->e)
    {
        insert(e,p->right);
        if( height(p->left) - height(p->right) == -2)
        {
            if (e > p->right->e)
                rotateRight(p);
            else
                rotateRightDouble(p);
        }
    }
    else // e ia already exist
    {   
        //return false;
    }
    p->h = max( height(p->left),height(p->right) )+1;
    return true;
}

template<typename Type> void AVLTree<Type>::rotateLeft(Node*& k2)
{
    Node* k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;

    k1->h = max( height(k1->left),height(k1->right) ) + 1;
    k2->h = max( height(k2->left),height(k2->right) ) + 1;
    k2 = k1;// join the original node
}

template<typename Type> void AVLTree<Type>::rotateRight(Node* &k2)
{
    Node* k1 = k2->right;
    k2->right = k1->left;
    k1->left = k2;

    k1->h = max( height(k1->left),height(k1->right) ) + 1;
    k2->h = max( height(k2->left),height(k2->right) ) + 1;
    //k1=k2,因为在insert函数中传入的是p->left或者p->right的引用,所以这里能把根结点赋给其父结点的子节点
    k2 = k1;
}

template<typename Type> void AVLTree<Type>::rotateLeftDouble(Node*& k3)
{
    rotateRight(k3->left);
    rotateLeft(k3);
}
template<typename Type> void AVLTree<Type>::rotateRightDouble(Node*& k3)
{
    rotateLeft(k3->right);
    rotateRight(k3);
}

template<typename Type> void AVLTree<Type>::traverse(Node* p)const
{
    if( p == NULL)
        return;
    else
    {
        traverse(p->left);
        cout<<"element:"<<p->e<<endl; //traverse by mid
        traverse(p->right);  
    }
}

template<typename Type> void AVLTree<Type>::traverseByLevel(Node* root)const
{
    if(root == NULL)
    {
        cout<<"The tree is empty"<<endl;
        return;
    }
    queue<Node*> que;
    que.push(root);
    while( !que.empty() )
    {
        Node* ptr = que.front();
        que.pop();
        cout<<"element:"<<ptr->e<<"    th:"<<height(ptr->left) - height(ptr->right)<<endl;
        if(ptr->left != NULL)
            que.push(ptr->left);
        if(ptr->right != NULL)
            que.push(ptr->right);
    }
}

template<typename Type> typename AVLTree<Type>::Node* & AVLTree<Type>::getParent(Node* p)
{  
    if( p == m_root)  
        return NULL;  
    Node* ptr = m_root;  
    Node* ptf = ptr;  
    while( ptr != NULL )  
    {  
        if ( ptr->e == p->e )  
            return ptf;  
        if ( ptr->e > p->e )  
        {  
            ptf = ptr;  
            ptr = ptr->leftChild;  
        }  
        else  
        {  
            ptf = ptr;  
            ptr = ptr->rightChild;
        }  
    }   
}

template<typename Type> typename AVLTree<Type>::Node*& AVLTree<Type>::find(Type e)const
{  
    Node* ptr = m_root;  

    while(ptr != NULL)  
    {  
        if ( ptr->e == e )  
            return ptr;  
        if ( ptr->e > e )  
            ptr = ptr->leftChild;  
        else  
            ptr = ptr->rightChild;  
    }  
    //if ( ptr == NULL )  
    return NULL;  
}

template<typename Type> void AVLTree<Type>::clears(Node*& p)
{
    if( p == NULL )
        return;
    else
    {
        clears(p->left);
        clears(p->right);
        delete p;
        p = NULL;
        mLength--;
    }
}

template<typename Type> void AVLTree<Type>::clear()
{
    clears(mRoot);
}

template<typename Type> void AVLTree<Type>::erase(Type e,Node* &p)
{
    if( p == NULL)
        return;
    if( e > p->e)
    {
        erase(e,p->right);
        if( height(p->left) - height(p->right) == 2)
        {
            if( height(p->left->left) > height(p->left->right) )
                rotateLeft(p);
            else
                rotateLeftDouble(p);
        }
    }
    else if( e < p->e)
    {
        erase(e,p->left);
        if( height(p->left) - height(p->right) == -2)
        {
            if( height(p->right->right) > height(p->right->left) )
                rotateRight(p);
            else
                rotateRightDouble(p);
        }
    }
    else if ( e == p->e && p->left!= NULL && p->right!= NULL)
    {
        Node* pmax = p->left;
        while( pmax->right != NULL)
        {
            pmax = pmax->right;
        }
        p->e = pmax->e;
        erase(p->e,p->left);
    }
    else //最终的删除会在这里执行
    {
        Node* pNew = p->left==NULL ? p->right : p->left;
        delete p;
        p = pNew;
        mLength--;
    }
    if ( p!=NULL)
        p->h = max( height(p->left),height(p->right)) + 1;
}
#endif[/code][b]main.cpp[code]//main.cpp
#include <iostream>
#include "AVLTree.h"
using namespace std;

void main()
{
    int Arr[9] = {6,2,8,4,10,0,12,16,14};
    AVLTree<int> Tr(Arr,9);
    Tr.traverse(Tr.getRoot());
    Tr.traverseByLevel(Tr.getRoot());

    Tr.erase(14,Tr.getRoot());
    Tr.traverse(Tr.getRoot());
    Tr.traverseByLevel(Tr.getRoot());
    cout<<"Tree's length is:"<<Tr.getLength()<<endl;
    Tr.clear();
    cout<<"Tree's length is:"<<Tr.getLength()<<endl;
}
回复

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2026-6-30 02:26 , Processed in 0.044720 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表