平衡二叉树(AVL)的另一种C++实现

平衡二叉树(AVL)的插入和删除详解(上):http://blog.csdn.net/sysu_arui/article/details/7897017

平衡二叉树(AVL)的插入和删除详解(下):http://blog.csdn.net/sysu_arui/article/details/7906303

前面详细介绍了平衡二叉树的插入和删除的实现,前面实现中结点使用的是一个值为-1、0、1的平衡因子bf,这里给出的实现其结点使用的域为高度height

空树高度为-1,单节点树高度为0,一棵树的高度等于其左子树高度和右子树高度中的较大者加1,通过比较左右子树的高度,我们很容易求出平衡因子,但是我们不显示的求平衡因子,因为平衡因子也就是左右子树的高度差,使用树的高度是便于平衡因子的维护。

前面讲解中,在插入和删除后,平衡因子变化很复杂,而下面给出的代码在插入和删除后只需要自顶向上求树的高度,不需要复杂的计算平衡因子,自己比较代码会有体会。

代码如下:

#include <cstdlib>
#include <iostream>

using namespace std;

template <typename Comparable>
class AVLTree
{
	public:
		
		AVLTree() : root(NULL){}
		AVLTree(const AVLTree & rhs) : root(NULL)
	    {
	        *this = rhs;
	    }
	    ~AVLTree()
	    {
	        makeEmpty();
	    }

	    /**
	     * Find the smallest item in the tree.
	     */
	    const Comparable & findMin() const
	    {
			if(!isEmpty())
			{
				return findMin(root)->element;
			}
	    }

	    /**
	     * Find the largest item in the tree.
	     */
	    const Comparable & findMax() const
	    {
	        if(!isEmpty())
	        {
				return findMax(root)->element;
			}
	    }

	    /**
	     * Returns true if x is found in the tree.
	     */
	    bool contains(const Comparable & x) const
	    {
			return contains(x, root);
	    }

	    /**
	     * Test if the tree is logically empty.
	     * Return true if empty, false otherwise.
	     */
	    bool isEmpty() const
	    {
	        return root == NULL;
	    }

	    /**
	     * Print the tree contents in sorted order.
	     */
	    void printTree() const
	    {
	        if(isEmpty())
	        {
	            cout << "Empty tree" << endl;
			}
	        else
	        {
	            printTree(root);
			}
	    }

	    /**
	     * Make the tree logically empty.
	     */
	    void makeEmpty()
	    {
	        makeEmpty(root);
	    }

	    /**
	     * Insert x into the tree; duplicates are ignored.
	     */
	    void insert(const Comparable & x )
	    {
	        insert(x,root);
	    }
	     
	    /**
	     * Remove x from the tree. Nothing is done if x is not found.
	     */
	    void remove(const Comparable & x)
	    {
			remove(x,root);
	    }

	    /**
	     * Deep copy.
	     */
	    const AVLTree & operator=(const AVLTree & rhs)
	    {
	        if( this != &rhs )
	        {
	            makeEmpty( );
	            root = clone(rhs.root);
	        }
	        return *this;
	    }
		
	private:
		struct AVLNode
	    {
	        Comparable element;
	        AVLNode* left;
	        AVLNode* right;
	        int height;
	
	        AVLNode(const Comparable & theElement, AVLNode *lt,
	                                                AVLNode *rt, int h = 0)
	          : element(theElement), left(lt), right(rt), height(h) {}
	    };
		
		AVLNode *root;


	    /**
	     * Internal method to insert into a subtree.
	     * x is the item to insert.
	     * t is the node that roots the subtree.
	     * Set the new root of the subtree.
	     */
	    void insert(const Comparable & x, AVLNode * & t)
	    {
	        if(t == NULL)
	        {
	            t = new AVLNode(x, NULL, NULL);
			}
	        else if(x < t->element)
	        {
	            insert(x, t->left);
	            if(height(t->left) - height(t->right) == 2)
	            	leftBalance(t);
//	                if(x < t->left->element)
//	                    rotateWithLeftChild(t);//LL rotate
//	                else
//	                    doubleWithLeftChild(t);//LR rotate
	        }
	        else if(t->element < x)
	        {
	            insert(x, t->right);
	            if( height(t->right) - height(t->left) == 2)
	            	rightBalance(t);
//	                if(t->right->element < x)
//	                    rotateWithRightChild(t);//RR rotate
//	                else
//	                    doubleWithRightChild(t);//RL rotate
	        }
	        else
	            ;  // Duplicate; do nothing
	        t->height = max(height(t->left), height(t->right)) + 1;
	    }	    
	    	
	    /**
	     * Internal method to remove in a subtree.
	     * x is the item to remove.
	     * t is the node that roots the subtree.
	     * Set the new root of the subtree.
	     */
	    void remove(const Comparable & x, AVLNode * & t)
	    {
	        if(t == NULL)				//no such element
	        {
				return;
			}
	        else if(x < t->element)		//find in left subtree
	        {
	            remove(x, t->left);
	            if(height(t->right) - height(t->left) == 2)
	            	rightBalance(t);
	        }
	        else if(t->element < x)		//find in right subtree
	        {
	            remove(x, t->right);
	            if( height(t->left) - height(t->right) == 2)
	            	leftBalance(t);
	        }
	        else						//delete node *t, 
	        {
				if(t->left == NULL)
				{
					AVLNode* q = t;
					t = t->right;
					delete q;
				}
				else if(t->right == NULL)
				{
					AVLNode* q = t;
					t = t->left;
					delete q;
				}
				else
				{
					t->element = findMax(t->left)->element;					
					remove(t->element,t->left);
					//t->element = findMin(t->right)->element;
					//remove(t->element,t->right);
				}
			}
	        if(t)			 
	        	t->height = max(height(t->left), height(t->right)) + 1;
	    }
	
	    /**
	     * Internal method to find the smallest item in a subtree t.
	     * Return node containing the smallest item.
	     */
	    AVLNode * findMin(AVLNode *t) const
	    {
	        if(t == NULL)
	            return NULL;
	        if(t->left == NULL)
	            return t;
	        return findMin(t->left);
	    }
	
	    /**
	     * Internal method to find the largest item in a subtree t.
	     * Return node containing the largest item.
	     */
	    AVLNode * findMax(AVLNode *t) const
	    {
	        if(t != NULL)
	            while(t->right != NULL)
	                t = t->right;
	        return t;
	    }
	
	
	    /**
	     * Internal method to test if an item is in a subtree.
	     * x is item to search for.
	     * t is the node that roots the tree.
	     */
	    bool contains(const Comparable & x, AVLNode *t) const
	    {
	        if( t == NULL )
	            return false;
	        else if( x < t->element )
	            return contains( x, t->left );
	        else if( t->element < x )
	            return contains( x, t->right );
	        else
	            return true;    // Match
	    }
		/****** NONRECURSIVE VERSION*************************
	    bool contains( const Comparable & x, AVLNode *t ) const
	    {
	        while( t != NULL )
	            if( x < t->element )
	                t = t->left;
	            else if( t->element < x )
	                t = t->right;
	            else
	                return true;    // Match
	
	        return false;   // No match
	    }
		*****************************************************/
	
	    /**
	     * Internal method to make subtree empty.
	     */
	    void makeEmpty(AVLNode * & t)
	    {
	        if(t != NULL)
	        {
	            makeEmpty(t->left);
	            makeEmpty(t->right);
	            delete t;
	        }
	        t = NULL;
	    }
	
		void preOrder(AVLNode *t)const
		{
			if(t)
			{
				cout<<t->element<<" ";
				preOrder(t->left);
				preOrder(t->right);
			}
		}
		
		void inOrder(AVLNode *t)const
		{
			if(t)
			{
				inOrder(t->left);
				cout<<t->element<<" ";
				inOrder(t->right);
			}
		}
		
	    /**
	     * Internal method to print a subtree rooted at t in sorted order.
	     */
	    void printTree(AVLNode *t) const
	    {
	        if(t)
	        {
				cout<<"preOrder: "<<endl;
				preOrder(t);
				cout<<endl;
				cout<<"inOrder: "<<endl;
				inOrder(t);
				cout<<endl;
	        }
	    }
	
	    /**
	     * Internal method to clone subtree.
	     */
	    AVLNode * clone(AVLNode *t) const
	    {
	        if( t == NULL )
	            return NULL;
	        else
	            return new AVLNode(t->element, clone(t->left), clone(t->right), t->height );
	    }
	        // Avl manipulations
	    /**
	     * Return the height of node t or -1 if NULL.
	     * since the height of a tree with single node is 0
	     */
	    int height(AVLNode *t) const
	    {
	        return t == NULL ? -1 : t->height;
	    }
	
	    int max(int lhs, int rhs) const
	    {
	        return lhs > rhs ? lhs : rhs;
	    }
	
	    /**
	     * Rotate binary tree node with left child.
	     * For AVL trees, this is a single rotation for case 1-LL.
	     * Update heights, then set new root.
	     */
	    void rotateWithLeftChild(AVLNode * & k2)
	    {
	        AVLNode *k1 = k2->left;
	        k2->left = k1->right;
	        k1->right = k2;
	        k2->height = max(height(k2->left), height(k2->right)) + 1;
	        k1->height = max( height(k1->left), k2->height) + 1;
	        k2 = k1;
	    }
	
	    /**
	     * Rotate binary tree node with right child.
	     * For AVL trees, this is a single rotation for case 4-RR.
	     * Update heights, then set new root.
	     */
	    void rotateWithRightChild(AVLNode * & k1)
	    {
	        AVLNode *k2 = k1->right;
	        k1->right = k2->left;
	        k2->left = k1;
	        k1->height = max(height(k1->left), height(k1->right)) + 1;
	        k2->height = max(height(k2->right), k1->height) + 1;
	        k1 = k2;
	    }
	
	    /**
	     * Double rotate binary tree node: first left child.
	     * with its right child; then node k3 with new left child.
	     * For AVL trees, this is a double rotation for case 2-LR.
	     * Update heights, then set new root.
	     */
	    void doubleWithLeftChild(AVLNode * & k3)
	    {
	        rotateWithRightChild( k3->left );
	        rotateWithLeftChild( k3 );
	    }
	
	    /**
	     * Double rotate binary tree node: first right child.
	     * with its left child; then node k1 with new right child.
	     * For AVL trees, this is a double rotation for case 3-RL.
	     * Update heights, then set new root.
	     */
	    void doubleWithRightChild(AVLNode * & k1)
	    {
	        rotateWithLeftChild(k1->right);
	        rotateWithRightChild(k1);
	    }
	    
	    /**
	     * left balance the subtree with root t 
	     * this method can use for both insert and delete
	     */
	    void leftBalance(AVLNode *& t)
	    {
			AVLNode* lc = t->left;
			if(height(lc->left) - height(lc->right) == -1)
			{
				doubleWithLeftChild(t);			//LR rotate		
			}
			else
			{
				rotateWithLeftChild(t);			//LL rotate
			}
		}
		
		/**
	     * right balance the subtree with root t 
	     * this method can use for both insert and delete
	     */
		void rightBalance(AVLNode *& t)
		{
			AVLNode* rc = t->right;
			if(height(rc->left) - height(rc->right) == 1)
			{
				doubleWithRightChild(t);		//RL rotate
			}
			else
			{
				rotateWithRightChild(t);		//RR rotate
			}
		}
};

int main(int argc, char *argv[])
{
	const int N = 20;
	AVLTree<int> t;
	
	//insert
	for(int i=0; i<N; i++)
	{
		t.insert(i);
	}
	cout<<"after insert:"<<endl;
	t.printTree();
	cout<<endl<<endl;
	
	//remove
	for(int i=1; i<N; i += 2)
	{
		t.remove(i);	
	}
	cout<<"after remove:"<<endl;
	t.printTree();
	cout<<endl<<endl;
	
	t.makeEmpty();
	
    system("PAUSE");
    return EXIT_SUCCESS;
}

注:

(1)实现中大部分代码来自参考资料[1],但是书中没有给出删除的具体实现,本人实现了一个,仅供参考。

(2)添加了左平衡和右平衡处理函数,是为了处理删除操作,但是该函数对插入操作也适用,看上面插入函数被注释的代码(被leftBalance函数和rightBalance函数替代)

参考资料:

[1]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )

[2][严蔚敏《数据结构(C语言版)》

[3]算法导论(第2版)P177

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/sysu_arui/article/details/7921498
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞