AVLTree的实现C++

普通的binary Search Tree的大量插入删除操作会造成树的不平衡,使得查找等操作效率不再为O(logn)。

AVLTree能够保证插入,删除,查找等操作在O(logn)内完成。

组成AVLTree的最少节点数与斐波那契数列的关系。

AVLTree的插入操作完成插入后需要更新节点的高度信息,并重新平衡此树, 找到发现问题的节点(imbalance factor == 2),并平衡以此节点为根节点的子树,然后新平衡树的根节点的祖先节点不需要更新, 因为平衡旋转后与插入前树的高度一样。

#ifndef AVL_TREE_H
#define AVL_TREE_H

#include <algorithm>
#include <iostream> 
using namespace std;

template<class Comparable>
class AVLTree {
public:
	// 优化代码,使得赋值操作简便
	friend void swap(AVLTree &, AVLTree &);

	AVLTree() : root(nullptr) {  }
	AVLTree(const AVLTree &rhs) : root(nullptr)
	{
		root = clone(rhs);
	}
	~AVLTree()
	{
		makeEmpty();
	}

	// deep copy
	AVLTree &operator=(const AVLTree &rhs)
	{
		AVLTree copy = rhs;
		swap(*this, copy);	// just swap like a pointer, 
		return *this;			// will call destructor when the method exits
	}

	AVLTree &operator=(AVLTree rhs)	// 避免了自赋值情况
	{
		std::swap(root, rhs.root);
		return *this;
	}

	// find the smallest item in the tree
	// Throw UnderflowException if empty
	const Comparable &findMin() const
	{
		if(isEmpty())
			throw UnderflowException();
		return findMin(root)->element;
	}
	
	const Comparable & findMax( ) const
    {
        if( isEmpty( ) )
            throw UnderflowException();
        return findMax( root )->element;
    }
	
	bool isEmpty() const
	{
		return root == nullptr;
	}

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

	
	void makeEmpty()
	{
		makeEmpty(root);
	}

	// insert x into the tree, duplicates are ignored.
	void insert(const Comparable &x)
	{
		insert(x, root);
	}

	void remove(const Comparable &x)
	{
		remove(x, root);
	}

	// print the tree contents in sorted order
	void printTree() const
	{
		if(isEmpty())
			cout << "Empty tree." << endl;
		else
			printTree(root);
	}
	
private:
	struct AVLNode
	{
		Comparable element;
		AVLNode *left;
		AVLNode *right;
		int height;

		AVLNode(const Comparable &ele, AVLNode *lt, AVLNode *rt, int h = 0)
			: element(ele), left(lt), right(rt), height(h) {  }
	};
			
	AVLNode *root;
	
	static const int ALLOWED_IMBALANCE = 1;		// imbalanced factor

    /**
     * Internal method to make subtree empty.
     */
    void makeEmpty( AVLNode * & t )
    {
        if( t != nullptr )
        {
            makeEmpty( t->left );
            makeEmpty( t->right );
            delete t;
        }
        t = nullptr;
    }

	/*
	 * Assume t is balanced or within one of being balanced
	 * there are 4 situations for balance
	 */
	void balance(AVLNode *&t)
	{
		if(t == nullptr)
			return;

		if(height(t->left) - height(t->right) > ALLOWED_IMBALANCE)
			if(height(t->left->left) >= height(t->left->right))
				rotateWithLeftChild(t);
			else
				doubleWithLeftChild(t);
		else 
			if(height(t->right) - height(t->left) > ALLOWED_IMBALANCE)
				if(height(t->right->right) >= height(t->right->left))
					rotateWithRightChild(t);
				else
					doubleWithRightChild(t);
		// update the current node's height	
		t->height = max(height(t->left), height(t->right)) + 1;			
	}

	int height(AVLNode *t) const
	{
		return t == nullptr ? -1 : t->height;	// set the height of nullptr-node to -1.
	}

	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 left-left rotation
	 * update heights, then set new root. 
	 * The height Only node k1 and k2 will be changed.
	 */
	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;	// update root node
	}

	/*
	 * Rotate binary tree node with right child.
	 * For a AVLtree ,this is a single rotation for right-right rotation.
	 * 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
	 * for insert into leftChild's rightSubTree left-right
	 */
	void doubleWithLeftChild(AVLNode *&k3)
	{
		rotateWithRightChild(k3->left);
		rotateWithLeftChild(k3);
	}

	/*
	 * Double rotate with right child.
	 * for insert into rightChild's leftSubTree  right-left
	 */
	void doubleWithRightChild(AVLNode *&k1)
	{
		rotateWithLeftChild(k1->right);
		rotateWithRightChild(k1);
	}

	
	/*
	 * Internal method to insert into a subtree. use recursive method.
	 * 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 == nullptr)
			t = new AVLNode(x, nullptr, nullptr);
		else if(x < t->element)
			insert(x, t->left);
		else if(t->element < x)
			insert(x, t->right);
		else
			;
		
		balance(t);	// make tree a AVLTree and update height
					// use recursive insertion algorithm to backfrom insertion node to root node
					// while find a node that violate AVLTree (balance |factor| >=2), ,then balance the node.
					// after balance that node ,the other father node will be balanced automaticly
	}

	void remove(const Comparable &x, AVLNode *&t)
	{
		if(t == nullptr)
			return;

		if(x < t->element)
			remove(x, t->left);
		else if(t->element < x)
			remove(x, t->right);
		else if(t->left != nullptr && t->right != nullptr) {
			t->element = findMin(t->right)->element;
			remove(x, t->right);
		}
		else {
			AVLNode *olfNode = t;
			t = (t->left != nullptr) ? t->left : t->right;
			delete oldNode;
		}

		balance(t);
	}

    /**
     * Internal method to print a subtree rooted at t in sorted order.
     */
    void printTree( AVLNode *t ) const
    {
        if( t != nullptr )
        {
            printTree( t->left );
            cout << t->element << endl;
            printTree( t->right );
        }
    }

	/*
	 * Internal method to find the smallest item in a subtree t
	 * return node containing the smallest item
	 */
	AVLNode *findMin(AVLNode *t) const
	{
		if(t == nullptr)
			return nullptr;
		if(t->left == nullptr)
			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 != nullptr )
			while( t->right != nullptr )
				t = t->right;
		return t;
	}
	
    /**
     * Internal method to clone subtree.
     */
    AVLNode * clone( AVLNode *t ) const
    {
        if( t == nullptr )
            return nullptr;
        else
            return new AvlNode{ t->element, clone( t->left ), clone( t->right ), t->height };
    }

	
};

inline void swap(AVLTree &lhs, AVLTree &rhs);

inline void swap(AVLTree &lhs, AVLTree &rhs)
{
	using std::swap;
	swap(lhs.root, rhs.root);
}

#endif		

 

 

下面为测试代码:

#include"AVLTree.h"
#include<stdlib.h>
#include<time.h>
#include<vector>

int main()
{
	AVLTree<int> tree1;
	srand(time(nullptr));
	vector<int> randomTreeElem;
	int nodeNum = 10;

	while (nodeNum--)
		randomTreeElem.push_back(rand() % 50);

	cout << "Test number are: " << endl;
	for (auto i : randomTreeElem)
		cout << i << ' ';
	cout << endl;

	for_each(randomTreeElem.begin(), randomTreeElem.end(), [&tree1](int elem) { tree1.insert(elem); });

	cout << "LevelTraversal of the AVLTree are: \n";
	tree1.printTree();
	cout << endl;

	return 0;
}

本测试随机生成了10个节点的AVLTree,然后打印tree, printTree是中序遍历tree,所以会得到递增的打印序列。

以下为测试结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值