avl树实现

本文详细介绍了一种自平衡二叉查找树——AVL树的实现原理与具体应用。包括异常处理、节点定义、插入删除操作及旋转调整等内容,并通过一个完整的C++实现示例进行说明。

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

//=================avl 的异常处理类=======================
//============== avl_tree_exception.h=====================
#ifndef AVL_TREE_EXCEPTION_H_
#define AVL_TREE_EXCEPTION_H_
#include<stdexcept>
#include<string>
class ATException: public std::logic_error
{
	public:
		ATException(const std::string &message="")
			:std::logic_error(message.c_str())
		{}
};
#endif


 

//====================avl_tree_item.h=====================
//===========存放节点中数据,包含两项关键字和值=========
#ifndef AVL_TREE_ITEM_H_
#define AVL_TREE_ITEM_H_
template<class ValT,class KeyT>
class Item
{
	private:
		ValT val;
		KeyT key;
	public:
		Item()
		{}
		Item(ValT &_val,KeyT &_key)
			:val(_val),key(_key)
		{
		}
		void set(ValT _val,KeyT _key)
		{
			val=_val;
			key=_key;
		}
		KeyT getKey()const
		{
			return key;
		}
		ValT getVal()const
		{
			return val;
		}
};
#endif


 

//========================avl_tree_node.h========================
//===================avl 树的节点,包含有========================
//===========左右孩子的指针 leftPtr and rightPtr=================
//=======bal 标识 该节点左右子树的相对高度LH  , EH or RH=========
#ifndef AVL_TREE_NODE_H_
#define AVL_TREE_NODE_H_
//mark the state of the current node
//LH----left subtree is higher than right subtree 1 node;		
//EH----left subtree is equal to right subtree;
//RH----left subtree is shorter than right subtree 1 node;
#define LH +1
#define EH 0
#define RH -1
template<class ItemT,class KeyT> class AvlTree;
template<class ItemT,class KeyT>
class Node
{
	private:
		
		ItemT item;
		Node *leftPtr,*rightPtr;
		int bal;
		Node(ItemT &_item,Node *_leftPtr,Node *_rightPtr)
			:item(_item),leftPtr(_leftPtr),rightPtr(_rightPtr)
		{
			bal=EH;
		}
		friend class AvlTree<ItemT,KeyT>;
};
#endif


 

//=======================avl_tree.h======================
//======================定义avl的类======================
#ifndef AVL_TREE_H_
#define AVL_TREE_H_
#include"avl_tree_exception.h"
#include"avl_tree_node.h"
template<class ItemT,class KeyT>
class AvlTree
{
	public:
		AvlTree();
		AvlTree(AvlTree &_tree);
		~AvlTree();

		void insert(ItemT &_item)throw(ATException);
		void remove(KeyT &_key)throw(ATException);
		void retrieve(KeyT &_key,ItemT &_item)throw(ATException);
		void traverse(void (*visit)(ItemT _item));
		bool empty()const;
	protected:
		void insertNode(Node<ItemT,KeyT> *&treePtr,ItemT & newitem,bool &taller)throw(ATException);

		void removeNode(Node<ItemT,KeyT> *&treePtr,KeyT &_key,bool &shorter)throw(ATException);

		//当平衡的avl树经过处理(insert or delete)后,失去原有的平衡,则调用
		//leftBalance 或者 rightBalance 函数处理,重新得到平衡
		void leftBalance(Node<ItemT,KeyT> *&treePtr,bool &state);
		void rightBalance(Node<ItemT,KeyT> *&treePtr,bool &state);

	
		void rotateLeft(Node<ItemT,KeyT> *&treePtr);
		void rotateRight(Node<ItemT,KeyT> *&treePtr);

		void retrieveNode(Node<ItemT,KeyT> *&treePtr,KeyT &_key,ItemT &_item)throw(ATException);
		
		void traverseNode(Node<ItemT,KeyT> *&treePtr,void (*visit)(ItemT _item));

		void copy(Node<ItemT,KeyT> *&treePtr,Node<ItemT,KeyT> *&oldPtr)throw(ATException);

		void destroy(Node<ItemT,KeyT> *&treePtr);

	private:
		Node<ItemT,KeyT> *root;
};
#endif


//=====================avl_tree.cpp======================
//===============avl_tree.h 的实现文件===================
#include<cstddef>
#include"avl_tree.h"
template<class ItemT,class KeyT>
AvlTree<ItemT,KeyT>::AvlTree()
{
	root=NULL;
}

template<class ItemT,class KeyT>
AvlTree<ItemT,KeyT>::AvlTree(AvlTree<ItemT,KeyT>& _tree)
{
	copy(root,_tree.root);
}

template<class ItemT,class KeyT>
AvlTree<ItemT,KeyT>::~AvlTree()
{
	destroy(root);
}
template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::insert(ItemT &_item)
	throw(ATException)
{
	bool taller=true;
	try{
		insertNode(root,_item,taller);
	}catch(ATException & e)
	{
		throw;
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::remove(KeyT &_key)
	throw(ATException)
{
	bool shorter=true;
	try{
		removeNode(root,_key,shorter);
	}catch(ATException &e)
	{
		throw;
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::retrieve(KeyT &_key,ItemT &_item)
	throw(ATException)
{
	try{
		retrieveNode(root,_key,_item);
	}catch(ATException &e)
	{
		throw;
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::traverse(void (*visit)(ItemT _item))
{
	traverseNode(root,visit);
}

template<class ItemT,class KeyT>
bool AvlTree<ItemT,KeyT>::empty()const
{
	return root==NULL;
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::insertNode(Node<ItemT,KeyT> *&treePtr,ItemT &newitem,bool &taller)
	throw(ATException)
{
	if(treePtr==NULL)
	{
		treePtr=new Node<ItemT,KeyT>(newitem,NULL,NULL);
		if(treePtr==NULL)
			throw ATException("allocate memory faild !");
		taller=true;
	}
	else if(newitem.getKey()<treePtr->item.getKey())
	{
		insertNode(treePtr->leftPtr,newitem,taller);
		if(taller)
		{
			switch(treePtr->bal)
			{
				case LH:leftBalance(treePtr,taller);
			            taller=false;
						break;
				case EH:treePtr->bal=LH;
						break;
				case RH:treePtr->bal=EH;
					    taller=false;
						break;
			}
		}
	}
	else
	{
		insertNode(treePtr->rightPtr,newitem,taller);
		if(taller)
		{
			switch(treePtr->bal)
			{
				case LH:treePtr->bal=EH;
						taller=false;
						break;
				case EH:treePtr->bal=RH;
						break;
				case RH:rightBalance(treePtr,taller);
						taller=false;
						break;
			}
		}
	} 
}

template<class ItemT ,class KeyT>
void AvlTree<ItemT,KeyT>::removeNode(Node<ItemT,KeyT>*&treePtr,KeyT &_key,bool &shorter)
	throw(ATException)
{
	if(treePtr==NULL)
		throw ATException("the key item not exist !");
	else if(_key<treePtr->item.getKey())
	{
		removeNode(treePtr->leftPtr,_key,shorter);
		if(shorter)
		{
			switch(treePtr->bal)
			{
				case LH:treePtr->bal=EH;
						break;
				case EH:treePtr->bal=RH;
						shorter=false;
						break;
				case RH:rightBalance(treePtr,shorter);
						break;
			}
		}
	}
	else if(_key>treePtr->item.getKey())
	{
		removeNode(treePtr->rightPtr,_key,shorter);
		if(shorter)
		{
			switch(treePtr->bal)
			{
				case LH:leftBalance(treePtr,shorter);
						break;
				case EH:treePtr->bal=LH;
						shorter=false;
						break;
				case RH:treePtr->bal=EH;
						break;
			}
		}
	}
	else
		//the item who's key word equal to _key exist
	{
		Node<ItemT,KeyT> *temp;
		if(treePtr->leftPtr==NULL)
			//the node pointer treePtr only has a right subtree 
			//  or is a leaf
		{
			temp=treePtr->rightPtr;
			treePtr->rightPtr=NULL;
			delete treePtr;
			treePtr=temp;
			shorter=true;
		}
		else if(treePtr->rightPtr==NULL)
			//the node pointer treePtr only has a left subtree
			//   or is a leaf
		{
			temp=treePtr->leftPtr;
			treePtr->leftPtr=NULL;
			delete treePtr;
			treePtr=temp;
			shorter=true;
		}
		else
			// the node pointer treePtr has both left subtree and
			//    right subtree 
		{
			temp=treePtr->rightPtr;
			while(temp->leftPtr!=NULL)
				temp=temp->leftPtr;
			treePtr->item=temp->item;
			removeNode(treePtr->rightPtr,temp->item.getKey(),shorter);
			if(shorter)
			{
				switch(treePtr->bal)
				{
					case LH:leftBalance(treePtr,shorter);
							break;
					case EH:treePtr->bal=LH;
							shorter=false;
							break;
					case RH:treePtr->bal=EH;
							break;
				}
			}
		}
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::leftBalance(Node<ItemT,KeyT> *&treePtr,bool &shorter)
{
	Node<ItemT,KeyT> *leftTree=treePtr->leftPtr;
	Node<ItemT,KeyT> *rightTree=leftTree->rightPtr;
	switch(leftTree->bal)
	{
		case LH:treePtr->bal=EH;
				leftTree->bal=EH;
				rotateRight(treePtr);
				break;
		case EH:treePtr->bal=LH;
				leftTree->bal=RH;
				rotateRight(treePtr);
				shorter=false;
				break;
		case RH:
			{
				switch(rightTree->bal)
				{
			    	case LH:treePtr->bal=RH;
							leftTree->bal=EH;
							break;
					case EH:treePtr->bal=EH;
							leftTree->bal=EH;
							break;
					case RH:treePtr->bal=EH;
							leftTree->bal=LH;
							break;
				}
			    rightTree->bal=EH;
				rotateLeft(leftTree);
				rotateRight(treePtr);
				break;
			}
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::rightBalance(Node<ItemT,KeyT>*&treePtr,bool &shorter)
{
	Node<ItemT,KeyT> *rightTree=treePtr->rightPtr;
	Node<ItemT,KeyT> *leftTree=rightTree->leftPtr;
	switch(rightTree->bal)
	{
		case LH:
			{
				switch(leftTree->bal)
				{
					case LH:treePtr->bal=EH;
							rightTree->bal=RH;
							break;
					case EH:treePtr->bal=EH;
							rightTree->bal=EH;
							break;
					case RH:treePtr->bal=LH;
							rightTree->bal=EH;
				}
				leftTree->bal=EH;
				rotateRight(rightTree);
				rotateLeft(treePtr);
				break;
			}
		case EH:treePtr->bal=RH;
				rightTree->bal=LH;
				rotateLeft(treePtr);
				shorter=false;
				break;
		case RH:treePtr->bal=EH;
				rightTree->bal=EH;
				rotateLeft(treePtr);
				break;
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::retrieveNode(Node<ItemT,KeyT>*&treePtr,KeyT &_key,ItemT &_item)
	throw(ATException)
{
	if(treePtr==NULL)
		throw ATException("found key item failed !");
	else if(_key<treePtr->item.getKey())
	{
		retrieveNode(treePtr->leftPtr,_key,_item);
	}
	else if(_key>treePtr->item.getKey())
	{
		retrieveNode(treePtr->rightPtr,_key,_item);
	}
	else
		_item=treePtr->item;
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::traverseNode(Node<ItemT,KeyT>*&treePtr,void (*visit)(ItemT _item))
{
	if(treePtr!=NULL)
	{
		traverseNode(treePtr->leftPtr,visit);
		visit(treePtr->item);
		traverseNode(treePtr->rightPtr,visit);
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::copy(Node<ItemT,KeyT> *&treePtr,Node<ItemT,KeyT>*&oldPtr)
	throw(ATException)
{
	if(oldPtr!=NULL)
	{
		treePtr=new Node<ItemT,KeyT>(oldPtr->item,NULL,NULL);
		if(treePtr==NULL)
			throw ATException("allocate memory failed !");
		treePtr->bal=oldPtr->bal;
		copy(treePtr->leftPtr,oldPtr->leftPtr);
		copy(treePtr->rightPtr,oldPtr->rightPtr);
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::destroy(Node<ItemT,KeyT>*& treePtr)
{
	if(treePtr!=NULL)
	{
		destroy(treePtr->leftPtr);
	    destroy(treePtr->rightPtr);
		delete treePtr;
		treePtr=NULL;	
	}
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::rotateLeft(Node<ItemT,KeyT> *&treePtr)
{
	Node<ItemT,KeyT>*temp=treePtr->rightPtr;
	treePtr->rightPtr=temp->leftPtr;
	temp->leftPtr=treePtr;
	treePtr=temp;
}

template<class ItemT,class KeyT>
void AvlTree<ItemT,KeyT>::rotateRight(Node<ItemT,KeyT>*&treePtr)
{
	Node<ItemT,KeyT> *temp=treePtr->leftPtr;
	treePtr->leftPtr=temp->rightPtr;
	temp->rightPtr=treePtr;
	treePtr=temp;
}


 

//=====================测试程序========================
#include<iostream>
#include<string>
#include<ctime>
#include<cstdlib>
#include"avl_tree_item.h"
#include"avl_tree.h"
#include"avl_tree.cpp"
using namespace std;
void display(Item<string,string> _item);
int main()
{
	//srand(time(0));
	AvlTree<Item<string,string>,string> atree;
	Item<string,string> newitem;
	string thekey,theval;
	cout<<"creating avl tree atree with 100 datas !"<<endl;
	for(int i=0;i<100;i++)
	{
		for(int j=0;j<10;j++)
		{
			thekey=thekey+char(rand()%26+'a');
			theval=theval+char(rand()%10+'0');
		}
		newitem.set(theval,thekey);
		try{
		atree.insert(newitem);
		thekey.clear();
		theval.clear();
		}catch(ATException &e)
		{
			cout<<e.what()<<endl;
		}
	}
	cout<<"the data in atree are :"<<endl;
	atree.traverse(display);
	cout<<"traverse the tree atree over !"<<endl;
	cout<<"enter the key word of the item (q to quit ):"<<endl;
	string keyword;
	cin>>keyword;
	while(keyword!="q")
	{
		try{
			atree.retrieve(keyword,newitem);
			display(newitem);
		}catch(ATException &e)
		{
			cout<<e.what()<<endl;
		}
		cout<<"enter other one key (q to quit): "<<endl;
		cin>>keyword;
	}
	cout<<"enter the key word of the item you want to delete (s to stop):"<<endl;
	cin>>keyword;
	while(keyword!="q")
	{
		try{
			atree.remove(keyword);
		}catch(ATException &e)
		{
			cout<<e.what()<<endl;
		}
		cout<<"enter other one key (s to stop):"<<endl;
		cin>>keyword;
	}
	cout<<"create a tree same as atree !"<<endl;
	AvlTree<Item<string,string>,string> btree(atree);
	cout<<"the date in btree :"<<endl;
	btree.traverse(display);
	cout<<"over !"<<endl;
	return 0;

}
void display(Item<string,string> _item)
{
	cout<< _item.getKey()<<'\t'<<_item.getVal()<<endl;
}


 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值