zoukankan      html  css  js  c++  java
  • C++模板实现的AVL树

    1 AVL树的定义

    AVL树是一种自平衡二叉排序树。它的特点是不论什么一个节点的左子树高度和右子树的高度差在-1,0,1三者之间。

    AVL树的不论什么一个子树都是AVL树。

    2 AVL树的实现

    AVL树本质是一种二叉排序树,所以二叉排序树的不论什么性质AVL树都具有。可是AVL树略微复杂的地方就是AVL树必须满足平衡条件。详细跟BST不同的地方主要体如今插入,删除操作。

    插入操作:当插入之后可能会出现不平衡,所以这时候要通过旋转树来实现平衡。

    旋转有四种类型,左左,左右,右左,右右。当中左左旋转和右右旋转是镜像的,左右旋转和右左旋转是镜像的,所以实质上就是两种类型的旋转。

    针对左左旋转。仅仅须要旋转一次就可以,针对左右旋转,须要运行两次旋转。见下图:


    这里採用递归法实现插入和删除操作。使用递归方便的一点是假设函数的參数是引用类型的,当传入一个p->left的时候。我们在当前函数的下层递归的时候,对p进行的赋值操作事实上就是对上层递归中的p->left进行的操作,所以这样就不须要传递父指针了。

    3 实现代码

    //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

    //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;
    
    }

    4 測试结果





  • 相关阅读:
    python_异常处理
    python_类与对象
    函数
    字符串(查找,替换,分割)
    容器类型的数据
    条件语句
    关于WinSock编程的多线程控制
    利用Delphi编写Socket通信程序
    SQL Server数据库开发的二十一条军规
    SQL Server中的日期格式化
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6806267.html
Copyright © 2011-2022 走看看