数据结构之AVL树

之前的博客,实现了数据结构中最基本的树形结构——二叉搜索树,下一步实现AVL树。这真的是很头疼的一颗树,无论是插入还是删除,都得分多种情况来讨论,其中的控制逻辑很繁琐。在编写代码之前,首先要想清楚在插入和删除的时候各个分支到底怎么处理,然后去编写代码。起码我现在看这部分内容,还是十分拧巴。多看看的话,应该会熟悉一点吧。

首先编写test.h:

#include<iostream>
#include<stack>
#include<assert.h>
using namespace std;

template<class Type>
class AVLTree;

template<class Type>
class AVLNode
{
	friend class AVLTree<Type>;
public:
	AVLNode() : data(Type()), leftChild(NULL), rightChild(NULL),bf(0)
	{}
	AVLNode(Type d, AVLNode<Type>*left=NULL,	AVLNode<Type>*right=NULL)
		:data(d), leftChild(left), rightChild(right),bf(0)
	{}
	~AVLNode()
	{}
public:
	Type GetData()const
	{return data;}
	AVLNode<Type>* GetLeftChild()const
	{return leftChild;}
	AVLNode<Type>* GetRightChild()const
	{return rightChild;}
public:
	void SetData(Type d)
	{data = d;}
	void SetLeftChild(AVLNode<Type> *left)
	{leftChild = left;}
	void SetRightChild(AVLNode<Type> *right)
	{rightChild = right;}
private:
	Type data;
	AVLNode<Type> *leftChild;
	AVLNode<Type> *rightChild;
	int bf;
};

template<class Type>
class AVLTree
{
public:
	AVLTree() : root(NULL)
	{}
public:
	bool Insert(const Type &x)
	{
		return Insert(root, x);
	}
	bool Remove(const Type &x)
	{
		return Remove(root, x);
	}
protected:
	//bool Remove(AVLNode<Type> *&t, const Type &x);
	bool Remove(AVLNode<Type> *&t, const Type &x)
	{
		AVLNode<Type> *pr = NULL, *p = t, *q, *ppr; int d, dd = 0;
		stack<AVLNode<Type>*> st;
		while (p != NULL) {
			if (x == p->data) break;
			pr = p; st.push(pr);
			if (x < p->data) {
				p = p->leftChild;
			} else {
				p = p->rightChild;
			}
		}
		if(p == NULL) return false;
		if (p->leftChild != NULL && p->rightChild != NULL) {
			pr = p;st.push(pr);
			q = p->leftChild;
			while (q->rightChild != NULL) {
				pr = q;st.push(pr);
				q = q->rightChild;
			}
			p->data = q->data;
			p = q;
		}
		if(p->leftChild != NULL) q = p->leftChild;
		else q = p->rightChild;
		if(pr == NULL) t = q;
		else{
			if(pr->leftChild == p) pr->leftChild = q;
			else pr->rightChild = q;
			while(st.empty() == false)
			{
				st.pop();
				if(pr->rightChild == q) pr->bf--;
				else pr->bf++;
				if(st.empty() == false)
				{
					ppr = st.top();
					dd = (ppr->leftChild == pr) ? -1 : 1;
				}
				else dd = 0;
				if(pr->bf == 1 || pr->bf == -1) break;
				if(pr->bf != 0)
				{
					if(pr->bf < 0){d = -1; q = pr->leftChild;}
					else{d = 1; q = pr->rightChild;}
					if(q->bf == 0)
					{
						if(d == -1)
						{RotateR(pr);pr->bf = 1; pr->leftChild->bf = -1;}
						else{RotateL(pr); pr->bf = -1; pr->rightChild->bf = 1;}
						break;
					}
					if(q->bf == d)
					{
						if(d == -1) RotateR(pr);
						else RotateL(pr);
					}
					else
					{
						if(d == -1) RotateLR(pr);
						else RotateRL(pr);
					}
					if(dd == -1) ppr->leftChild = pr;
					else if(dd == 1) ppr->rightChild = pr;
				}
				q = pr;
			}
			if(st.empty() == true) t = pr;
		}
		delete p ;return true;
	}
	bool Insert(AVLNode<Type> *&t, const Type &x)
	{
		AVLNode<Type> *pr = NULL;
		AVLNode<Type> *p = t;
		
		stack<AVLNode<Type>*> 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<Type>(x);
		if(pr == NULL)
		{
			t = p;
			return true;
		}

		if(p->data < pr->data)
			pr->leftChild = p;
		else
			pr->rightChild = p;
		

		while(!st.empty())
		{
			pr = st.top();
			st.pop();
			if(pr->leftChild == p)
				pr->bf--;
			else
				pr->bf++;

			if(pr->bf == 0)
				break;
			else if(pr->bf==1 || pr->bf==-1)
				p = pr;
			else
			{
				if(pr->bf < 0)
				{
					if(p->bf < 0)    //     /
					{
						RotateR(pr);
					}
					else              //    <
					{
						RotateLR(pr);
					}
				}
				else
				{
					if(p->bf > 0)    //    \   
					{
						RotateL(pr);
					}
					else              //    >
					{
						RotateRL(pr);
					}
				}
				break;
			}
		}

		if(st.empty())
			t = pr;
		else
		{
			AVLNode<Type> *q = st.top();
			if(q->data > pr->data)
				q->leftChild = pr;
			else
				q->rightChild = pr;
		}
		return true;
	}
protected:
	void RotateR(AVLNode<Type> *& ptr)
	{
		AVLNode<Type> *subR = ptr;
		ptr = subR->leftChild;
		subR->leftChild = ptr->rightChild;
		ptr->rightChild = subR;
		
		ptr->bf = subR->bf = 0;
	}
	void RotateL(AVLNode<Type> *& ptr)
	{
		AVLNode<Type> *subL = ptr;
		ptr = subL->rightChild;
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;

		ptr->bf = subL->bf = 0;
	}
	void RotateLR(AVLNode<Type> *& ptr)
	{
		AVLNode<Type>*subR = ptr;
        AVLNode<Type>*subL = ptr->leftChild;
		ptr = subL->rightChild;
		
		//左转
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;
		if(ptr->bf <= 0)
			subL->bf = 0;
		else
			subL->bf = -1;

		subR->leftChild = ptr->rightChild;
		ptr->rightChild = subR;
		if(ptr->bf >= 0)
			subR->bf = 0;
		else
			subR->bf = 1;		

		ptr->bf = 0;
	}
	void RotateRL(AVLNode<Type> *& ptr)
	{
		AVLNode<Type> *subL = ptr;
		AVLNode<Type> *subR = ptr->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<Type> *root;
};

测试程序test.cpp:

#include"Test.h"

void main()
{
	int ar[] = {16,3,7,11,9,26,18,14,15};
	int n = sizeof(ar) / sizeof(int);
	AVLTree<int> avl;
	for(int i=0; i<n; ++i)
	{
		avl.Insert(ar[i]);
	}

	avl.Remove(11);
	return;
}

我的笔记本上有三个C++的编译器,分别是年代很久远的VC++6.0,clion,codeblocks,后面两个都是gcc的编译器。我本人比较偏爱cb,但是它在调试查看变量反面实在是短板,前面两个表现都不错,值得表扬。我就在想是不是cb的设置有问题呢?

AVL树真的很难啊。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值