现在的位置: 首页 > 综合 > 正文

AVL平衡二叉树左平衡和右平衡算法实现及说明

2014年01月30日 ⁄ 综合 ⁄ 共 3410字 ⁄ 字号 评论关闭

参考链接:

http://www.cnblogs.com/hustcat/archive/2008/04/13/1151586.html

《数据结构(C语言版)》p237介绍了平衡二叉树的左平衡算法void LeftBalance(BSTree &T);
对于该算法的理解可以参考p235的图9.13的图例。

备注:
LeftBalance的代码片段:

	case EH:
		T->bf = lc->bf = EH;
		break;

可以对照9.13的图例的b,当C为新插入节点(Cl=Cr=NULL,Bl=NULL,Ar=NULL),此时B的bf由0->-1,A的bf由1->2,双旋之后A,B,C的bf都为0

完整示例代码:

#include <iostream>

#define LH 1	//左高
#define EH 0	//等高
#define RH -1	//右高

typedef int Status;

typedef struct ElemType {
	struct ElemType(int e) : key(e) {}
	int key;
}ElemType;

typedef struct BSTNode {
	ElemType data;
	int bf;								//节点的平衡因子
	struct BSTNode *lchild, *rchild;	//左、右孩子指针
}BSTNode, *BSTree;

void R_Rotate(BSTree &p) {
	//对以*p为根的二叉排序树作右旋处理,处理之后p指向新的树根节点,即旋转
	//处理之前的左子树的根节点
	BSTree lc = p->lchild;		//lc指向的*p的左子树根节点
	p->lchild = lc->rchild;		//lc的右子树挂接为*p的左子树
	lc->rchild = p;	p = lc;		//p指向新的根节点
}//R_Rotate

void L_Rotate(BSTree &p) {
	//对以*p为根的二叉排序树作左旋处理,处理之后p指向新的节点,即旋转
	//处理之前的右子树的根节点
	 BSTree rc = p->rchild;	//rc指向的*p的右子树的根节点
	 p->rchild = rc->lchild;	//rc的左子树挂接为*p的右子树
	 rc->lchild = p; p = rc;	//p指向新的根节点
}//L_Rotate

void LeftBalance(BSTree &T) {
	//对以指针T所指的节点为根的二叉树作左平衡处理,本算法结束时,指针T指向
	//新的根节点
	BSTree lc = T->lchild;		//lc指向*T的左子树根节点
	switch (lc->bf) {			//检查*T的左子树的平衡度,并作相应的平衡处理
		case LH:				//新节点插入在*T的左孩子的左子树上,要作单右旋处理
			T->bf = lc->bf = EH;
			R_Rotate(T);
			break;
		case RH:				//新节点插入在*T的左孩子的右子树上,要作双旋处理
			BSTree rd = lc->rchild;	//rd指向*T的左孩子的右子树根
			switch (rd->bf) {	//修改*T及其左孩子的平衡因子
				case LH:
					T->bf = RH;
					lc->bf = EH;
					break;
				case EH:
					T->bf = lc->bf = EH;
					break;
				case RH:
					T->bf = EH;
					lc->bf = LH;
					break;
			} //switch (rd->bf)
			rd->bf = EH;
			L_Rotate(T->lchild);	//对*T的左子树作左旋平衡处理
			R_Rotate(T);			//对*T作右旋平衡处理
			break;
	} //switch (lc->bf)
} //LeftBalance

void RightBalance(BSTree &T) {
	//对以指针T所指的节点为根的二叉树作右平衡处理,本算法结束时,指针T指向
	//新的根节点
	BSTree rc = T->rchild;		//rd指向*T的右子树根节点
	switch (rc->bf) {			//检查*T的右子树的平衡度,并作相应的平衡处理
		case RH:				//新节点插入在*T的右孩子的右子树上,要作单左旋处理
			T->bf = rc->bf = EH;
			L_Rotate(T);
			break;
		case LH:				//新节点插入在*T的右孩子的左子树上,要作双旋处理
			BSTree ld = rc->lchild;	//ld指向*T的右孩子的左子树根
			switch (ld->bf) {	//修改*T及其右孩子的平衡因子
				case RH:
					T->bf = LH;
					rc->bf = EH;
					break;
				case EH:
					T->bf = rc->bf = EH;
					break;
				case LH:
					T->bf = EH;
					rc->bf = RH;
					break;
			} //switch (ld->bf)
			ld->bf = EH;
			R_Rotate(T->rchild);
			L_Rotate(T);
			break;
	} //switch (rc->bf)
} //RightBalance

Status InsertAVL(BSTree &T, ElemType e, bool &taller) {
	//若在平衡的二叉树T中不存在和e有相同关键字的节点,则插入一个数据元素
	//为e的新节点,并返回1,否则返回0。若因插入而使二排序树失去平衡,则作平衡
	//旋转处理,布尔变量taller反映T长高与否
	if (!T) { //插入新节点,树“长高”,置taller为TRUE
		T = (BSTree)malloc(sizeof(BSTNode));
		T->data = e;
		T->lchild = T->rchild = NULL;
		T->bf = EH;
		taller = true;
	}
	else {
		if (e.key == T->data.key) {	//树中已存在和e有相同关键字的节点
			taller = false;				//则不插入
			return 0;
		}
		if (e.key < T->data.key) {	//应继续在*T的左子树中进行搜索
			if (!InsertAVL(T->lchild, e, taller))
				return 0;				//未插入
			if (taller)	{				//已插入到*T的左子树中且左子树“长高”
				switch (T->bf) {		//检查*T的平衡度
					case LH:			//原本左子树比右子树高,需要作左平衡处理
						LeftBalance(T); 
						taller = false;
						break;
					case EH:			//原本左、右子树登高,现因左子树增高而使树增高
						T->bf = LH; 
						taller = true;
						break;
					case RH:			//原本右子树比左子树高,现左、右子树等高
						T->bf = EH; 
						taller = false;
						break;
				} //switch(T->bf)
			} //if(taller)
		}//if
		else {							//应继续在*T的右子树中进行搜索
			if (!InsertAVL(T->rchild, e, taller))
				return 0;				//未插入
			if (taller) {				//已插入到*T的右子树并且右子树长高
				switch (T->bf) {		//检查*T的平衡度
					case LH:			//原本左子树比右子树高,现左、右子树等高
						T->bf = EH; taller = false;
						break;
					case EH:			//原本左、右子树等高,现因右子树增高而使树增高
						T->bf = RH; taller = true;
						break;
					case RH:			//原本右子树比左子树高,需要作右平衡处理
						RightBalance(T); taller = false;
						break;
				} //switch(T->bf)
			} //if(taller)
		} //else
	} //else
	return 1;
} //InsertAVL

void InOrderTraverse(BSTree root) {		//中序遍历
	if (root) {
		InOrderTraverse(root->lchild);
		std::cout << root->data.key << ", ";
		InOrderTraverse(root->rchild);
	}
}

int main()
{
	BSTree root = NULL;
	BSTree r;

	bool taller = false;

	int array[] = {13,24,37,90,53};

	for (int i = 0; i < 5; ++i) {
		InsertAVL(root, array[i], taller);
	}

	std::cout << "inorder travese..." << std::endl;
	InOrderTraverse(root);
	return 0;
}

输出结果:
inorder travese...
13, 24, 37, 53, 90, Press any key to continue

抱歉!评论已关闭.