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

原创 2012年03月30日 10:44:34

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

首先吧,关于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;
}


AVL树及C语言实现

概念   平衡二叉树(Balanced binary tree)是由苏联数学家Adelson-Velskii and Landis于1962年首先提出的,所以又称为AVL树。 定义:平衡二叉树或...
  • IT_PCode
  • IT_PCode
  • 2014年03月28日 23:34
  • 1864

AVL树实现与分析

AVL是高度平的二叉搜索树,它能降低二叉树的高度,减少树的平均搜索长度
  • he_shuai20
  • he_shuai20
  • 2017年04月27日 23:50
  • 868

AVL树的C++实现 Implement of AVL tree

AVL是一种自平衡的二叉查找树。 不同于普通的二叉查找树之处在于:每个节点的左右子树高度差最多为1,故每个节点多了一个高度(height)属性。 其实现难点在于插入和删除时要检测节点高度差是否满足上述...
  • showonstage1
  • showonstage1
  • 2014年03月31日 22:51
  • 1436

自己动手实现数据结构——AVL树(C++实现)

这类教程有很多了,就用C++简单实现下以供记录和参考,以后再有补充版本。 实现了查找和插入、删除操作有些复杂,感觉个人实现的效率不是很高,以后再补充,先把做过的东西记录下来。 Avl.h #ifn...
  • sshhiixx
  • sshhiixx
  • 2015年08月10日 13:06
  • 1436

AVL树的旋转图解和简单实现

AVL树是带有平衡条件的查找二叉树。这个平衡条件要容易保持,而且他要保证树的深度为O(logN)原文地址:http://blog.csdn.net/qq_25806863/article/detail...
  • qq_25806863
  • qq_25806863
  • 2017年07月07日 18:03
  • 470

C++模板实现的AVL树

1 AVL树的定义 AVL树是一种自平衡二叉排序树,它的特点是任何一个节点的左子树高度和右子树的高度差在-1,0,1三者之间。AVL树的任何一个子树都是AVL树。 2 AVL树的实现 AVL树本质是一...
  • zhuhuangtianzi
  • zhuhuangtianzi
  • 2014年11月03日 18:40
  • 999

AVL树的java实现

AVL树的定义自己百度去,这里给出自己用java的一个实现。 package test; /** * @时间 2014-3-30 * @version 0.1 * @encode UTF-8...
  • dahlwuyn
  • dahlwuyn
  • 2014年03月31日 16:07
  • 4346

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

这几天学习了AVL树(平衡二叉搜索树),遂写一篇总结与大家分享。包括五个部分: 一、AVL树(平衡二叉搜索树)是什么? 二、为什么要用AVL树? 三、AVL树的实现原理 四、完整的实现代码(C++和J...
  • u013149325
  • u013149325
  • 2014年11月22日 21:46
  • 1710

python数据结构学习笔记-2016-12-10-01-AVL树

14.3 AVL树         AVL树由G.M.Adel‘son-Velskii和Y.M.Landis在1962年发明的自平衡二叉查找树。如果一个二叉树,其左右两子树的高度最多相差1,则称该二...
  • baidu_21088863
  • baidu_21088863
  • 2016年12月31日 18:55
  • 177

数据结构与算法分析(三) —— AVL树的实现

本文实现了AVL树,有几个注意点:insert和remove引起的失衡都可以用同样的旋转进行修复: Case1:k2的左子树的左子树比其右子树高2 —— k2进行左单旋 Case4:k1的右子树的右子...
  • lipengcn
  • lipengcn
  • 2016年07月21日 10:07
  • 796
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:AVL树实现类——二叉链表实现
举报原因:
原因补充:

(最多只允许输入30个字)