平衡二叉树的实现

添加链接描述
参照上面的博客 实现了一下平衡二叉树,这段代码花费了我很多的时间 ,主要是没有跳出里面的循环 下面附上代码 会在代码中介绍具体算法

#include <iostream>
using namespace std;
//二叉树的二叉链表结构
typedef struct node
{
	int bf;	//平衡因子
	int key;	//数据
	struct node *leftChild, *rightChild; //左孩子,右孩子指针
}BBSTNode;

const int LH = 1; // 左子树高于右子树
const int RH = -1; //右子树高于左子树
const int EH = 0;	//左右子树等高



//针对LL型的树结构做右旋
void RightRotate(BBSTNode *& p)
{
	BBSTNode * lc;//lc指向p的左子树的根节点
	lc = p->leftChild;
	p->leftChild = lc->rightChild;//让lc的右子树挂接p的左子树的位置
	lc->rightChild = p;//p结点挂载在lc的右子数位置
	p = lc; //lc变成新的根节点
}


//针对RR型的树结构做左旋
void LeftRotate(BBSTNode *& p)
{
	BBSTNode * rc;//lc指向p的右子树根节点
	rc = p->rightChild;
	p->rightChild = rc->leftChild;//将rc的左子树挂载在p的右子树上
	rc->leftChild = p;//p挂在lc的左子树上
	p = rc; //rc变为新的根节点
}

//左子树因长高而失衡
void LeftBalance(BBSTNode *& root)
{
	BBSTNode * lc; //根的左子树
	lc = root->leftChild;//lc指向root树的左子树根结点

	switch(lc->bf)
	{//检查root左子树的平衡度
	case LH:
		//如果是左边高 那么就行右旋处理
		lc->bf = root->bf = EH;	//修改根和左子树的平衡因子
		RightRotate(root);
		break;
	case RH:
		//如果新结点插入在T的左孩子的右子树上  要做双旋处理
		BBSTNode * rd; //根的左子树的右子树
		rd = lc->rightChild;//rd指向root的左孩子的右子树上
		switch(rd->bf)
		{
		case LH:
			lc->bf = EH, root->bf = RH;
			break;
		case EH:
			lc->bf = root->bf = EH;
			break;
		case RH://这一步没太看明白
			root->bf = EH, lc->bf = LH;
			break;
		}
		rd->bf = EH;
		LeftRotate(root->leftChild);
		RightRotate(root);
		break;
	}
}

//右子树因长高而失衡
void RightBalance(BBSTNode *& root)
{
	BBSTNode * rc; //根的右子树
	rc = root->rightChild;
//检查右子树
	switch(rc->bf)
	{
	case RH:
		root->bf = EH, rc->bf = EH;
		LeftRotate(root);
		break;

	case LH:
		BBSTNode * ld;
		ld = rc->leftChild;
		switch(ld->bf)
		{
		case LH:
			root->bf = EH, rc->bf = RH;
			break;
		case EH:
			root->bf = rc->bf = EH;
			break;
		case RH:
			root->bf = LH, rc->bf = EH;
			break;
		}
		ld->bf = EH;
		RightRotate(root->rightChild);
		LeftRotate(root);
		break;
	}
}

//递归插入数据
int insertAVL(BBSTNode * & root, int key, bool & taller)
{
	if(!root) //根节点为空则插入之
	{
		root = new BBSTNode();//申请一块空间
		root->key = key;//数据域赋值
		root->leftChild = root->rightChild = NULL;//左右孩子指针指向空
		root->bf = EH;//平衡因子设置为等高
		taller = true;//增高标志
	}
	else
	{
		if(key == root->key)//如果树中有同关键字的结点 则不再插入
		{
			taller = false;
			return 0;
		}
		else if(key < root->key)//在根结点的左字数中插入
		{
			if(!insertAVL(root->leftChild, key, taller))//递归遍历
			{
				//如果没有插入成功  返回0
				return 0;
			}
			if(taller)//已经查到左子树中 且左子树长高了
			{
				switch(root->bf)//检查T的平衡度
				{
				case LH://原本左子树比右子树高,现在结点还加到了左子树上 需要做平衡处理
					LeftBalance(root);
					taller = false;
					break;
				case EH://原本左右子树等高  现在因为左子树增高而增高
					root->bf = LH;
					taller = true;
					break;




				case RH://原本右子树高  现在左右子树登高
					root->bf = EH;
					taller = false;
					break;
				}
			}
		}
		else
		{//在右子树中插入
			if(!insertAVL(root->rightChild, key, taller))
			{
				return 0;
			}
			if(taller)
			{
				switch(root->bf)
				{
				case LH:
					root->bf = EH;
					taller = false;
					break;
				case EH:
					root->bf = RH;
					taller = true;
					break;
				case RH://原本右子树比左子树高 现在点还插在了右边  所需需要做平衡处理
					RightBalance(root);
					tallerxuexi = false;
					break;
				}
			}
		}
	}
}

//中序遍历平衡二叉树
void in(BBSTNode * root)
{
	if(root)
	{
		in(root->leftChild);
		cout << root->key << '\t';
		in(root->rightChild);
	}
}


int main()
{
	BBSTNode * root; //平衡二叉树的根指针
	root = NULL; //跟指针初始化
	int a[10]={3,2,1,4,5,6,7,10,9,8};
	bool taller;

	//建树,没输入一个结点,则输出中序遍历序
	for(int i=0;i<10;i++)
	{
		insertAVL(root, a[i], taller);
		in(root);
		cout << endl;
	}
	return 0;
}


下面是运行的结果

3	
2	3	
1	2	3	
1	2	3	4	
1	2	3	4	5	
1	2	3	4	5	6	
1	2	3	4	5	6	7	
1	2	3	4	5	6	7	10	
1	2	3	4	5	6	7	9	10	
1	2	3	4	5	6	7	8	9	10	

在这段代码中 卡住了很久

else if(key < root->key)//在根结点的左字数中插入
128                 {
129                         if(!insertAVL(root->leftChild, key, taller))//递归遍历
130                         {
131                                 //如果没有插入成功  返回0
132                                 return 0;
133                         }
134                         if(taller)//已经查到左子树中 且左子树长高了
135                         {
136                                 switch(root->bf)//检查T的平衡度
137                                 {
138                                 case LH://原本左子树比右子树高,现在结点还加到了左子树上 需要做平衡处理
139                                         LeftBalance(root);
140                                         taller = false;
141                                         break;
142                                 case EH://原本左右子树等高  现在因为左子树增高而增高
143                                         root->bf = LH;
144                                         taller = true;
145                                         break;
146 
147 
148 
149 
150                                 case RH://原本右子树高  现在左右子树登高
151                                         root->bf = EH;
152                                         taller = false;
153                                         break;
154                                 }
155                         }
156                 }

这里由于每次循环 root都是更新的 我之前在手动运算的时候 结果偏差比较多 .原因就是我一开始把root带入,但是在循环中 root可能是root->leftchild等 再一层层退出循环 ,就能得到结论 手动运算一遍收获比较大!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值