AVL树的学习

#include "bitree.h"

//定义几个宏来表示当前的状态
#define AVL_LFT_HEAVY 1
#define AVL_BALANCED 0
#define AVL_RGT_HEAVY -1

//用二叉树类型来实现BST
typedef BiTree BisTree;

//定义AVL树的基本结构
typedef struct AvlNode_{

	//数据
	void	*data;

	int	hidden;
	int	factor;
		
}AvlNode;

/*
姚锟注,其实这里还有很多东西,还没有写完,没有实现,而且本身代码也是抄的书上的~、
但是对于平衡树旋转还是有那么一小点点的理解滴~
以后熟练了再去做吧
*/

//公共的接口
bistree_init

//这个销毁函数的复杂度是on
bistree_destroy

//删除节点
bistree_remove

//左平衡旋转函数
static void rotate_left(BiTreeNode **node){

	BiTreeNode	*left,
				*grandchild;

	//取出左子树
	left = bitree_left(*node);

	if( ((AvlNode *)bitree_data(left))->factor == AVL_LFT_HEAVY ){
		
		//LL旋转
		bitree_left(*node) = bitree_right(left);
		bitree_right(left) = *node;
		
		//left在顶部和A节点本身都是平衡的了
		((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
		((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
		
		*node = left;
	}

	else{
		//完成一个LR旋转
		
		//保存一个孙子节点,是left节点的右节点
		grandchild					= bitree_right(left);
		bistree_right(left)			= bistree_left(grandchild);
		bistree_left(grandchild)	= left;
		bistree_left(*node)			= bitree_right(grandchild);
		bistree_right(grandchild)	= *node;

		//修正平衡因子
		switch( ((AvlNode *)bitree_data(grandchild))->factor ){
			case AVL_LFT_HEAVY:
				((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY;
				((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
				break;
			
			case AVL_BALANCED:
				((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
				((AvlNode *)bitree_data(left))->factor = AVL_BALANCED;
				break;

			case AVL_RGT_HEAVY:
				((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
				((AvlNode *)bitree_data(left))->factor = AVL_LFT_HEAVY;
				break;
		}

		//反正最终grandchild是平衡的了
		((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED;
		*node = grandchild;

	}
	
	//返回了
	return ;
}

//右平衡旋转函数
static void rorate_right(BiTreeNode **node){
	BiTreeNode		*right,
					*grandchild;
	
	right	= bitree_right(*node);
	if((AvlNode *)bitree_data(right))->factor == AVL_RGT_HEAVY){
		//完成一个RR旋转
		bitree_right(*node)	= bitree_left(right);
		bitree_left(right)	= *node;
		
		((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
		((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
		*node	= right;	
	}

	else{
		//完成一个RL旋转
		grandchild = bitree_left(right);

		bitree_left(right)			= bitree_right(grandchild);
		bitree_right(grandchild)	= right;
		bitree_right(*node)			= bitree_left(grandchild);
		bitree_left(grandchild)		= *node;

		//还是那样,做出一些平衡
		switch (((AvlNode *)bitree_data(grandchild))->factor) {
			case AVL_LFT_HEAVY:
				((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
				((AvlNode *)bitree_data(right))->factor = AVL_RGT_HEAVY;
				break;

			case AVL_BALANCED:

				((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
				((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
				break;

			case AVL_RGT_HEAVY:

				((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY;
				((AvlNode *)bitree_data(right))->factor = AVL_BALANCED;
      			break;

		}

		((AvlNode *)bitree_data(grandchild))->factor = AVL_BALANCED;
		
		*node	= grandchild;
	}
	
	return ;
}

/*
 插入节点,更新平衡因子
 1.如果是空树,则直接设置为ROOT,更新平衡因子
 2.需要对节点的数据进行比较,找寻应该插入的位置
找到插入的位置,就分配一个AvlNode结构体,插入树中[还有一种隐藏的情况,很复杂]
*/
static int insert(BisTree *tree, BiTreeNode **node, const void *data, int *balanced){

	AvlNode	*avl_data;
	
	//字面意思就看出来是比较值和返回值嘛
	int		cmpval,
			retval;

	//插入节点
	
	//插入到空树中
	if( bitree_is_eob(*node)){
		//插入空树中

		//开辟空间
		if ( (avl_data = new AvlNode) == NULL )
			return -1;

		avl_data->factor	= AVL_BALANCED;
		avl_data->hidden	= 0;
		avl_data->data		= (void *)data;

		return bitree_ins_left(tree, *node, avl_data);

	}

	else{
	
		cmpval	= tree->compare(data, ((AvlNode *)bitree_data(*node))->data);

		if(cmpval < 0){
			//To Left
			
			if(bitree_is_eob(bitree_left(*node))){
				//如果插入节点的左面是空的,准备插入
			
			if ( (avl_data = new AvlNode) == NULL )
				return -1;
			
			avl_data->factor	= AVL_BALANCED;
			avl_data->hidden	= 0;
			avl_data->data		= (void *)data;

			if( bitree_ins_left(tree, *node, avl_data) != 0 )
				return -1;

			//这个时候应该是不平衡的
			*balanced = 0;
			
			}

			//这是当做节点不为空的时候的递归插入
			else{
				if( (retval = insert(tree, &bitree_left(*node), data, balanced)) != 0 )
					return retval;

			}

			//确定树仍旧保持平衡
			if(!(*balanced)){
			//其实吧,这个过程就是更新平衡因子
			switch( ((AvlNode *)bitree_data(*node))->factor ){
				case AVL_LFT_HEAVY:
					//这样加的话应该是变成2了,需要左旋转了
					rotate_left(node);
					*balanced = 1;
					break;

				case AVL_BALANCED:	
					((AvlNode *)bitree_data(*node))->factor = AVL_LFT_HEAVY;
					break;

				case AVL_RGT_HEAVY:
					((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;
					*balanced = 1;
				
				}
			}
			
		} /*这个是cmp<0的终止 */

		//往右面插入啊
		else if(cmpval > 0){
			
			if(bitree_is_eob(bitree_right(*node)))	{
				//直接往右面插入
				if((avl_data = new AvlNode) == NULL)
					return -1;

				avl_data->factor	= AVL_BALANCED;
				avl_data->hidden	= 0;
				avl_data->data		= (void *)data;

				if (bitree_ins_right(tree, *node, avl_data) != 0)
					return -1;	
			}
			else{
				if( (retval = insert(tree, &bitree_right(*node), data, balanced)) != 0 )
					return retval;
			}

			//保持平衡哟
			if(!(*balanced)){
				
				switch( ((AvlNode *)bitree_data(*node))->factor ){
					case AVL_LFT_HEAVY:
						((AvlNode *)bitree_data(*node))->factor = AVL_BALANCED;	
						*balanced = 1;
						break;

					case AVL_BALANCED:
						((AvlNode *)bitree_data(*node))->factor = AVL_RGT_HEAVY;
						break;

					case AVL_RGT_HEAVY:
						rotate_right(node);
						*balanced = 1;	
				}
			}

		} //cmp>0

		else{
			//刚刚好找到了这个元素

			if( !((AvlNode *)bitree_data(*node)->hidden)){
				//数据就真实的在,那么就什么都不做,直接返回
				return 1;
			}
			else{
				if (tree->destroy != NULL) {
					//删除这个隐藏的元素
					tree->destroy(((AvlNode *)bitree_data(*node))->data);
				}
				
				((AvlNode *)bitree_data(*node))->data = (void *)data;
				((AvlNode *)bitree_data(*node))->hidden = 0;

				//树的结构并没有改变,所以什么都不干
				*balanced = 1;

			}
			
		} /*对应cmp的最后一个分支*/
	}

	return 0;

}


你可能感兴趣的:(AVL树---算法精解)