关闭

AVL树实现类——二叉链表实现

标签: pathclassnullinsertdeletealgorithm
1103人阅读 评论(0) 收藏 举报
分类:

(一个人感冒咳嗽不悲剧,悲剧的是全家都感冒咳嗽,没人做事……忽冷忽热的天气得注意保暖)

首先吧,关于AVL树的知识,还是老规矩,Wiki下。

“在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。

节点的平衡因子是它的右子树的高度减去它的左子树的高度。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。”

这样,对AVL树就能大概理解了。然后吧,就来温习下主要的插入和删除操作实现。

其实,这个两个操作都可以分成两个步骤,一个是普通操作(删除、插入),另个是平衡操作。

普通操作,就是简单的寻找到需要删除或者插入的节点位置,把寻找路径保存起来(我用数组模拟栈保存)。对于插入操作,就直接将新节点插入到该位置即可。对于删除操作,则需要翻阅点资料了。也有两大类吧,删除同时有左右子树的节点,这样的话,就可以通过其中序前驱节点替换实现。如果说最多只有一棵子树,那么就好办了,就用子树替换吧。

平衡操作呢,也可以再细分成两个步骤。一个是树结构的变换,另一个是树节点平衡因子的更新。树结构的变换的话,可以看看四种旋转及其应用条件(http://tc.itkee.com/media/detail-a06.html这篇文章介绍得蛮详细的,就不多敲了)。然后平衡因子的更新,只用更新那几个子树结构变化了的节点。

这些理解了的话,那就容易理解我实现的AVL类了。(代码虽长,因为考虑到要缩小函数规模,功能分得比较细;另外,有专门用来测试的函数。个人资源有0分方便下载http://download.csdn.net/detail/betabin/4185761

/*
Author:BetaBin
Date:2012/03/30
AboutMe:http://blog.csdn.net/BetaBin
*/
#include <iostream>

using namespace std;

#define MAX_DEPTH 32

//AVL树节点类
template <class NodeType>
class AvlNode
{
public:
	int balancedfactor;
	NodeType value;
	AvlNode<NodeType> *lChild, *rChild;

	AvlNode();
	AvlNode(NodeType data);
};

template <class NodeType>
AvlNode<NodeType>::AvlNode()
{
	balancedfactor = 0;
	lChild = NULL;
	rChild = NULL;
}

template <class NodeType>
AvlNode<NodeType>::AvlNode(NodeType data)
{
	balancedfactor = 0;
	lChild = NULL;
	rChild = NULL;
	value = data;
}

//AVL树模板类
template <class NodeType>
class AvlTree
{
public:
	AvlTree();
	~AvlTree();
	void DestroyTree(AvlNode<NodeType> *node);	//销毁以node为根的AVL树
	bool InsertValue(NodeType value);			//插入新值value
	bool RemoveValue(NodeType value);			//移除值为value的节点

	AvlNode<NodeType>* GetRoot();				//获取Root指针
	void InfixOutput(AvlNode<NodeType> *node);	//中序输出节点信息,用于测试。NodeType必须重载<<输出符号

private:
	AvlNode<NodeType> *root;					//根节点
	AvlNode<NodeType> *path[MAX_DEPTH];			//实现路径保存栈
	int pathLen;								//路径实际长度 - 1,配合path数组模拟栈

	//四种旋转
	AvlNode<NodeType>* LLRotate(AvlNode<NodeType> *rotateRoot);
	AvlNode<NodeType>* LRRotate(AvlNode<NodeType> *rotateRoot);
	AvlNode<NodeType>* RRRotate(AvlNode<NodeType> *rotateRoot);
	AvlNode<NodeType>* RLRotate(AvlNode<NodeType> *rotateRoot);

	bool FindPosition(NodeType value); //用于插入函数,寻找存放value的位置,并插入,保存寻找路径至path数组。节点已经存在则返回false,否则为true
	void InsertBalanced(NodeType value);	//插入操作后平衡树
	void RemoveBalanced(NodeType value);	//删除操作后平衡树
	bool RotateTree();	//用于旋转树(以当前path[pathLen]为根节点的树),并且判断该子树旋转后高度是否变化,变化返回true,否则返回false
	void RemoveNode(AvlNode<NodeType> *node);	//用于删除该节点,并且更新平衡因子信息
};

template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::GetRoot()
{
	return root;
}

template <class NodeType>
void AvlTree<NodeType>::InfixOutput(AvlNode<NodeType> *node)
{
	if (NULL == node)
	{
		return ;
	}

	InfixOutput(node->lChild);
	cout << "###    " << node->value << endl;
	InfixOutput(node->rChild);
}

template <class NodeType>
AvlTree<NodeType>::AvlTree()
{
	root = NULL;
	pathLen = 0;
}

template <class NodeType>
AvlTree<NodeType>::~AvlTree()
{
	DestroyTree(root);
}

template <class NodeType>
void AvlTree<NodeType>::DestroyTree(AvlNode<NodeType> *node)
{
	if (NULL == node)
	{
		return ;
	}

	DestroyTree(node->lChild);
	DestroyTree(node->rChild);
	delete node;
}

template <class NodeType>
bool AvlTree<NodeType>::FindPosition(NodeType value)
{
	pathLen = 0;
	AvlNode<NodeType> *prevnode = NULL;
	AvlNode<NodeType> *currentnode = root;

	//保存从根到值为value的节点该存放位置的路径到模拟栈中
	while (currentnode != NULL)
	{
		path[pathLen++] = currentnode;

		//原值已经存在,插入查找失败
		if (currentnode->value == value)
		{
			return false;
		}

		prevnode = currentnode;
		if (currentnode->value < value)
		{
			currentnode = currentnode->rChild;
		} 
		else
		{
			currentnode = currentnode->lChild;
		}
	}

	//将该value值插入到相应位置
	currentnode = new AvlNode<NodeType>(value);
	currentnode->balancedfactor = 0;

	if (value < prevnode->value)
	{
		prevnode->lChild = currentnode;
	} 
	else
	{
		prevnode->rChild = currentnode;
	}

	path[pathLen] = currentnode;

	return true;
}

template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::LLRotate(AvlNode<NodeType> *rotateRoot)
{
	//树结构变换
	AvlNode<NodeType> *newRoot = rotateRoot->lChild;
	rotateRoot->lChild = newRoot->rChild;
	newRoot->rChild = rotateRoot;

	//平衡因子调整
	if (1 == newRoot->balancedfactor)
	{
		rotateRoot->balancedfactor = 0;
		newRoot->balancedfactor = 0;
	} 
	//删除操作出现平衡因子为0
	else
	{
		rotateRoot->balancedfactor = 1;
		newRoot->balancedfactor = -1;
	}

	return newRoot;
}

template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::LRRotate(AvlNode<NodeType> *rotateRoot)
{
	//树结构变换
	AvlNode<NodeType> *nextNode = rotateRoot->lChild;
	AvlNode<NodeType> *newRoot = nextNode->rChild;
	rotateRoot->lChild = newRoot->rChild;
	nextNode->rChild = newRoot->lChild;
	newRoot->rChild = rotateRoot;
	newRoot->lChild = nextNode;

	//平衡因子调整
	switch (newRoot->balancedfactor)
	{
	case 0:
		rotateRoot->balancedfactor = 0;
		nextNode->balancedfactor = 0;
		break;
	case 1:
		rotateRoot->balancedfactor = -1;
		nextNode->balancedfactor = 0;
		break;
	case -1:
		rotateRoot->balancedfactor = 0;
		nextNode->balancedfactor = 1;
		break;
	default:
		return NULL;
	}

	newRoot->balancedfactor = 0;
	return newRoot;
}

template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::RRRotate(AvlNode<NodeType> *rotateRoot)
{
	//树结构变换
	AvlNode<NodeType>* newRoot = rotateRoot->rChild;
	rotateRoot->rChild = newRoot->lChild;
	newRoot->lChild = rotateRoot;

	//平衡因子调整
	if (-1 == newRoot->balancedfactor)
	{
		rotateRoot->balancedfactor = 0;
		newRoot->balancedfactor = 0;
	} 
	else
	{
		rotateRoot->balancedfactor = -1;
		newRoot->balancedfactor = 1;
	}

	return newRoot;
}

template <class NodeType>
AvlNode<NodeType>* AvlTree<NodeType>::RLRotate(AvlNode<NodeType> *rotateRoot)
{
	//树结构调整
	AvlNode<NodeType>* nextNode = rotateRoot->rChild;
	AvlNode<NodeType>* newRoot = nextNode->lChild;
	rotateRoot->rChild = newRoot->lChild;
	nextNode->lChild = newRoot->rChild;
	newRoot->lChild = rotateRoot;
	newRoot->rChild = nextNode;
	
	//平衡因子调整
	switch (newRoot->balancedfactor)
	{
	case 0:
		rotateRoot->balancedfactor = 0;
		nextNode->balancedfactor = 0;
		break;
	case 1:
		rotateRoot->balancedfactor = 0;
		nextNode->balancedfactor = -1;
		break;
	case -1:
		rotateRoot->balancedfactor = 1;
		nextNode->balancedfactor = 0;
		break;
	default:
		return NULL;
	}

	newRoot->balancedfactor = 0;
	return newRoot;
}

//根据平衡因子判断需要进行的旋转类型,并进行旋转操作
//同时判断旋转之后树高度是否变化,用于删除操作
//高度变化返回true,否则返回false
template <class NodeType>
bool AvlTree<NodeType>::RotateTree()
{
	bool isHeightChanged = true;
	AvlNode<NodeType> *oldRoot = path[pathLen];	//通过模拟栈找到需要调整的根
	AvlNode<NodeType> *newRoot;
	int originalRootBf = oldRoot->balancedfactor;

	if (2 == originalRootBf)
	{
		int leftBf = oldRoot->lChild->balancedfactor;
		if (1 == leftBf)
		{
			newRoot = LLRotate(oldRoot);
		}
		else if (-1 == leftBf)
		{
			newRoot = LRRotate(oldRoot);
		}
		//删除操作会出现平衡因子为0的情况
		else
		{
			newRoot = LLRotate(oldRoot);
			isHeightChanged = false;
		}
	} 

	if (-2 == originalRootBf)
	{
		int rightBf = oldRoot->rChild->balancedfactor;
		if (1 == rightBf)
		{
			newRoot = RLRotate(oldRoot);
		}
		else if (-1 == rightBf)
		{
			newRoot = RRRotate(oldRoot);
		}
		//删除操作会出现平衡因子为0的情况
		else
		{
			newRoot = RRRotate(oldRoot);
			isHeightChanged = false;
		}
	}

	//更新根的父亲节点的指针
	if (pathLen > 0)
	{
		if (oldRoot->value < path[pathLen - 1]->value)
		{
			path[pathLen - 1]->lChild = newRoot;
		}
		else
		{
			path[pathLen - 1]->rChild = newRoot;
		}
	}
	else
	{
		root = newRoot;
	}

	return isHeightChanged;	
}

template <class NodeType>
void AvlTree<NodeType>::InsertBalanced(NodeType value)
{
	int bf = 0;
	while (pathLen > 0)
	{
		bf = (path[pathLen - 1]->value > value) ? 1 : -1;
		path[--pathLen]->balancedfactor += bf;
		bf  =path[pathLen]->balancedfactor;

		//遇到平衡因子变为1或者-1表示该子树平衡没有遭到破坏,既可以不用再平衡其祖宗
		if (0 == bf)
		{
			break;
		}
		else if (2 == bf || -2 == bf)
		{
			RotateTree();
		}
	}
}

template<class NodeType>
void AvlTree<NodeType>::RemoveBalanced(NodeType value)
{
	int bf = 0;
	while (pathLen > 0)
	{
		bf = (path[pathLen - 1]->value >= value) ? -1 : 1;
		path[--pathLen]->balancedfactor += bf;
		bf = path[pathLen]->balancedfactor;

		if (0 != bf)
		{
			//遇到平衡因子变为1或者-1表示该子树平衡没有遭到破坏,既可以不用再平衡其祖宗
			//删除操作后,遇到树高度不变化,也可不用再平衡其祖宗
			if (1 == bf || -1 == bf || !RotateTree())
			{
				break;
			}
		}
	}
}

template <class NodeType>
bool AvlTree<NodeType>::InsertValue(NodeType value)
{
	if (NULL == root)
	{
		root = new AvlNode<NodeType>(value);
		return true;
	}

	if ( false == FindPosition(value))
	{
		//该值的节点已经存在,不需要重复插入
		return true;
	}

	InsertBalanced(value);
	return true;
}

template <class NodeType>
void AvlTree<NodeType>::RemoveNode(AvlNode<NodeType> *node)
{
	AvlNode<NodeType> *tempNode = NULL;

	//有左右子树
	if (NULL != node->lChild && NULL != node->rChild)
	{
		tempNode = node->lChild;
		path[++pathLen] = tempNode;

		//找到该node的中序前驱节点
		while (NULL != tempNode->rChild)
		{
			tempNode = tempNode->rChild;
			path[++pathLen] = tempNode;
		}
		node->value = tempNode->value;
		//更新中序前驱节点的父节点儿子指针
		if (node == path[pathLen - 1])
		{
			path[pathLen - 1]->lChild = tempNode->lChild;
		} 
		else
		{
			path[pathLen - 1]->rChild = tempNode->lChild;
		}
	} 
	//最多只有一个子树时
	else
	{
		tempNode = node->lChild;
		if (NULL == tempNode)
		{
			tempNode = node->rChild;
		}
		//删除的是非根节点
		if (pathLen > 0)
		{
			if (path[pathLen - 1]->lChild == node)
			{
				path[pathLen - 1]->lChild = tempNode;
			}
			else
			{
				path[pathLen - 1]->rChild = tempNode;
			}
		}
		else
		{
			root = tempNode;
		}

		tempNode = node;
	}

	RemoveBalanced(node->value);

	delete tempNode;
}

template <class NodeType>
bool AvlTree<NodeType>::RemoveValue(NodeType value)
{
	pathLen = -1;
	AvlNode<NodeType> *node = root;
	
	while (NULL != node)
	{
		path[++pathLen] = node;

		if (value == node->value)
		{
			RemoveNode(node);
			return true;
		}

		if (node->value < value)
		{
			node = node->rChild;
		}
		else
		{
			node = node->lChild;
		}
	}
	return false;
}

int main()
{
	AvlTree<int> test;
	int n;
	int data;
	int operation;
	
	while (true)
	{
		cout << "Please select operation(0 for insert, 1 for remove, others for exit):";
		cin >> operation;

		if (0 == operation)
		{
			cout << "How many number do you want to insert:";
			cin >> n;
			while (n--)
			{
				cin >> data;
				test.InsertValue(data);
			}
		}
		else if (1 == operation)
		{
			cout << "How many number do you want to remove:";
			cin >> n;
			while (n--)
			{
				cin >> data;
				test.RemoveValue(data);
			}
		}
		else
		{
			break;
		}
		cout << "Result:" << endl;
		test.InfixOutput(test.GetRoot());
	}

	return 0;
}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:528671次
    • 积分:5778
    • 等级:
    • 排名:第4629名
    • 原创:125篇
    • 转载:29篇
    • 译文:0篇
    • 评论:26条
    文章分类
    最新评论