码迷,mamicode.com
首页 > 编程语言 > 详细

AVLTree的C++实现

时间:2015-05-27 14:03:31      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

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


template<class T>
class AVLTree;

template <class T>
class AVLNode
{
	friend class AVLTree<T>;
public:
	AVLNode():leftChild(NULL),rightChild(NULL),bf(0)
	{}
	AVLNode(T t,AVLNode<T>* l=NULL, AVLNode<T>* r=NULL):data(t),leftChild(l),rightChild(r),bf(0)
	{}
	~AVLNode()
	{}
private:
	AVLNode<T>* leftChild;
	AVLNode<T>* rightChild;
	T data;
	int bf;  //平衡因子
};

template<class T>
class AVLTree
{
public:
	AVLTree():root(NULL)
	{}
	AVLTree(T Ref):Refvalue(Ref),root(NULL)
	{}
	~AVLTree()
	{}
	bool Insert( T &x)
	{
		return Insert(root,x);
	}
	void PrintAVLTree()
	{
		PrintAVLTree(root);
	}
	void PrintTree()
	{
		PrintTree(root);
	}
	void Print()
	{
		Print(root);
	}
	bool Remove(const T x)
	{
		return Remove(root,x);
	}
protected:
	bool Remove(AVLNode<T>* &t,const T x)
	{
		AVLNode<T> *parent=NULL, *q , *ppr,*p = t;
		stack<AVLNode<T> *> st;
		int d,dd=0;
		while(p != NULL)
		{
			if(x == p->data)
				break;
			parent = p;
			st.push(parent);
			if(x < p->data)
				p = p->leftChild;
			else
				p = p->rightChild;
		}
		if(p == NULL)
			return false;
		if(p->leftChild != NULL && p->rightChild != NULL) //被删节点有两个子女
		{
			parent = p;
			st.push(parent);
			q = p->leftChild;
			while(q->rightChild != NULL)
			{
				parent = q;
				st.push(parent);
				q = q->rightChild;
			}
			p->data = q->data;
			p = q;  //被删节点转化为q
		}
		if(p->leftChild != NULL)
			q = p->leftChild;
		else
			q = p->rightChild;
		if(parent == NULL)
			t = q;
		else
		{
			if(parent->leftChild == p)
				parent->leftChild = q;
			else
				parent->rightChild = q;
			while(!st.empty())
			{
				//parent = st.top();  //
				st.pop();
				if(parent->rightChild == q)
					parent->bf --;  //
				else
					parent->bf ++;//
				if(!st.empty())
				{
					ppr = st.top();  //祖父节点
					dd = (ppr->leftChild == parent) ? -1 : 1;
				}
				else
					dd=0;
			if(parent->bf == 1 || parent->bf == -1)
				break;
			if(parent->bf != 0)
			{
				if(parent->bf < 0)
				{
					d = -1;
					q = parent->leftChild;
				}
				else
				{
					d = 1;
					q = parent->rightChild;
				}
				if(q->bf == 0)
				{
					if(d == -1)
					{
						RotateR(parent);
						parent->bf = 1;
						parent->leftChild->bf = -1;
					}
					else
					{
						RotateL(parent);
						parent->bf = -1;
						parent->rightChild->bf =1;
					}
					break;
				}
			if(q->bf == d)
			{
				if(d == -1)
					RotateR(parent);
				else
					RotateL(parent);
			}
			else
			{
				if(d == -1)
					RotateLR(parent);
				else
					RotateRL(parent);
			}
			if(dd == -1)
				ppr->leftChild = parent;
			else if(dd == 1)
				ppr->rightChild = parent;
		}
		q = parent;
	}
		if(st.empty())
			t = parent;
	}
		delete p;
		return true;
	}
	void PrintAVLTree(AVLNode<T>* &t)//中序遍历
	{
		if(t != NULL)
		{
			PrintAVLTree(t->leftChild);
			cout<<t->data<<" ";
			PrintAVLTree(t->rightChild);
		}
	}
	void PrintTree(AVLNode<T> *& t)  //后序
	{
		if(t != NULL)
		{
			PrintTree(t->rightChild);
			cout<<t->data<<" ";
			PrintTree(t->leftChild);
		}
	}
	void Print(AVLNode<T> *& t) //前序
	{
		if(t != NULL)
		{
			cout<<t->data<<" ";
			Print(t->leftChild);
			Print(t->rightChild);
		}
	}
	bool Insert(AVLNode<T> * &t, T &x)
	{
		AVLNode<T> *pr = NULL, *p = t, *q;
		int d;
		stack<AVLNode<T> *> st;
		while(p != NULL)  //寻找插入位置
		{
			if(x == p->data)
				return false;
			pr = p;
			st.push(pr);
			if(x < p->data)
				p = p->leftChild;
			else
				p = p->rightChild;
		}
		p = new AVLNode<T>(x); //创建新节点,data=x,bf=0
		if(p == NULL)
		{
			cerr<<"存储空间不足"<<endl;
			exit(1);
		}
		if(pr == NULL) //空树,新节点成为根节点
		{
			t = p;
			return true;
		}
		if(x < pr->data)
			pr->leftChild = p; //新节点插入
		else
			pr->rightChild = p;
		while(!st.empty())
		{
			pr = st.top();
			st.pop();
			if(p == pr->leftChild)
				pr->bf --;
			else
				pr->bf ++;
			if(pr->bf == 0)  
				break;  //平衡退出
			if(pr->bf == 1 || pr->bf == -1)
				p = pr;       
			else   //|bf|==2 
			{
				d = (pr->bf < 0) ? -1 : 1;  //区别单双旋转标志
 				if(p->bf == d)  //两节点平衡因子同号,单旋转
				{
					if(d == -1)
						RotateR(pr);
					else
						RotateL(pr);
				}
				else
				{
					if(d == -1)
						RotateLR(pr);
					else
						RotateRL(pr);
				}
				break;            //不再向上调整
			}	
		}
		if(st.empty())
			t = pr;
		else
		{
			q = st.top();
			if(q->data > pr->data)
				q->leftChild = pr;
			else
				q->rightChild = pr;
		}
		return true;
	}
	void RotateL(AVLNode<T>* &ptr)  //左旋转
	{
		AVLNode<T> *subL = ptr; //要旋转的节点
		ptr = subL->rightChild;
		subL->rightChild = ptr->leftChild; //ptr成为新根前卸掉左边负载
		ptr->leftChild = subL;  //左单旋转,ptr为新根
		ptr->bf = subL->bf = 0;	
	}
	void RotateR(AVLNode<T>* &ptr) //右旋转
	{
		AVLNode<T> *subR = ptr;
		ptr = subR->leftChild;
		subR->leftChild = ptr->rightChild;  //先卸掉右边负载
		ptr->rightChild = subR;
		ptr->bf = subR->bf = 0;
	}
	void RotateLR(AVLNode<T>* &ptr)  //先左后右双旋转
	{
		AVLNode<T> *subR = ptr, *subL = subR->leftChild;
		ptr = subL->rightChild;
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;
		if(ptr->bf <= 0)
			subL->bf = 0;  //插入新节点后ptr左子树变高
		else
			subL->bf = -1;
		subR->leftChild = ptr->rightChild; //甩掉ptr右边的负载
		ptr->rightChild = subR;
		if(ptr->bf == -1)
			subR->bf = 1;
		else
			subR->bf = 0;
		ptr->bf = 0;
	}
	void RotateRL(AVLNode<T> * &ptr)
	{
		AVLNode<T> *subL = ptr,*subR = subL->rightChild;
		ptr = subR->leftChild;
		subR->leftChild = ptr->rightChild;  //先卸掉负载
		ptr->rightChild = subR;
		if(ptr->bf >= 0)
			subR->bf = 0;
		else
			subR->bf = 1;
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;
		if(ptr->bf == 1)
			subL->bf = -1;
		else
			subL->bf = 0;
		ptr->bf = 0;
	}

private:
	AVLNode<T> *root;
	T         Refvalue;  //结束标志
};

void main()
{
	int a[] = {9,53,5,45,17,23,78,65,34,87};
	AVLTree<int> avl;
	for(int i=0; i<10; ++i)
		avl.Insert(a[i]);
	avl.PrintAVLTree();
	cout<<endl;
//	avl.PrintTree();
//	cout<<endl;
//	avl.Print();
//	cout<<endl;
	avl.Remove(45);
	avl.PrintAVLTree();
	cout<<endl;
}

AVLTree的C++实现

标签:

原文地址:http://blog.csdn.net/lc331257229/article/details/46044891

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!