数据结构与算法分析 c++11 AVL tree 另一种实现方法

本文介绍了一种AVL树的实现方式,该实现通过在插入和删除操作中调整左右子树来保持平衡。文中提供了AVL树的C++模板类定义及关键方法,包括插入、删除、查找最小值和最大值等,并详细解释了旋转操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


  AVL tree 的另一种实现方法,这种AVL tree 是在插入删除过程中分别考虑左右子树的平衡,调用左右调整规则“leftBalance(t)  和 rightBalance(t)”,并及时调整。 第四版书上P125页介绍的是放弃平衡条件,允许有任意的深度,但是在每次操作之后使用一个调整规则(P125 调整规则void balance(AvlNode * &t))调整。


AVLTree.h 

#pragma once
#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;

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

	void insert(const Comparable & x, AVLNode * & t);
	void remove(const Comparable & x, AVLNode * & t);
	/**
	* 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;
	}

	bool contains(const Comparable & x, AVLNode *t) const;
	/****** NONRECURSIVE VERSION*************************/
	bool contains(const Comparable & x, AVLNode *t);
	void makeEmpty(AVLNode * & t);
	void preOrder(AVLNode *t)const;
	void inOrder(AVLNode *t)const;
	void printTree(AVLNode *t) const;

	/**
	* 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. */
	void rotateWithLeftChild(AVLNode * & k2);
	/** Rotate binary tree node with right child.*/
	void rotateWithRightChild(AVLNode * & k1);

	/*Double rotate binary tree node: first left child with its right child;*/
	void doubleWithLeftChild(AVLNode * & k3);
	void doubleWithRightChild(AVLNode * & k1);

	void leftBalance(AVLNode *& t);
	void rightBalance(AVLNode *& t);
};



template<typename Comparable>
inline void AVLTree<Comparable>::printTree() const
{
	if (isEmpty())
	{
		cout << "Empty tree" << endl;
	}
	else
	{
		printTree(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.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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 test if an item is in a subtree.
* x is item to search for.
* t is the node that roots the tree.
*/
template<typename Comparable>
inline bool AVLTree<Comparable>::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  
}

template<typename Comparable>
inline bool AVLTree<Comparable>::contains(const Comparable & x, AVLNode * t)
{
	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.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::makeEmpty(AVLNode *& t)
{
	if (t != NULL)
	{
		makeEmpty(t->left);
		makeEmpty(t->right);
		delete t;
	}
	t = NULL;
}

template<typename Comparable>
inline void AVLTree<Comparable>::preOrder(AVLNode * t) const
{
	if (t)
	{
		cout << t->element << " ";
		preOrder(t->left);
		preOrder(t->right);
	}
}

template<typename Comparable>
inline void AVLTree<Comparable>::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.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::printTree(AVLNode * t) const
{
	if (t)
	{
		cout << "preOrder: " << endl;
		preOrder(t);
		cout << endl;
		cout << "inOrder: " << endl;
		inOrder(t);
		cout << endl;
	}
}


/**
* 用左儿子旋转二叉树的节点
* 这是对AVL 树在情形1的一次单旋转
* 更新高度,然后设置新根。
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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;
}
/**
* 用右儿子旋转二叉树的节点
* 这是对AVL 树在情形4的一次单旋转
* 更新高度,然后设置新根。
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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;
}

/**
* 双旋转二叉树的节点: 首先左儿子和它的右儿子进行。
* 然后节点k3和新的左儿子进行
* For AVL trees, this is a double rotation for case 2-LR.
* Update heights, then set new root.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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.
*/
template<typename Comparable>
inline void AVLTree<Comparable>::doubleWithRightChild(AVLNode *& k1)
{
	rotateWithLeftChild(k1->right);
	rotateWithRightChild(k1);
}
/**
* left balance the subtree with root t
* this method can use for both insert and delete
*/
template<typename Comparable>
inline void AVLTree<Comparable>::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
*/
template<typename Comparable>
inline void AVLTree<Comparable>::rightBalance(AVLNode *& t)
{
	AVLNode* rc = t->right;
	if (height(rc->left) - height(rc->right) == 1)
	{
		doubleWithRightChild(t);        //RL rotate  
	}
	else
	{
		rotateWithRightChild(t);        //RR rotate  
	}
}

main.cpp

#include "AVLTree.h"

using namespace std;

int main(int argc, char *argv[])
{
	const int N = 25;
	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();

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值