不用平衡因子及父节点来实现平衡二叉树

本文介绍了一种平衡二叉树的插入算法,通过四种不同情况的分析,确保树的平衡性。算法详细描述了如何在插入节点后,通过旋转操作调整树结构,保持左子树和右子树的高度差不超过1,实现树的平衡。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      // 不是 很会用图片来进行描述我的插入想法 在这里只能简单口述一下
//   最核心的想法就是  始终以最上面的三个节点来调整二叉树  让其达到平衡
//情况分为四种   
//第一种  当头节点的左节点的左节点造成了树的不平衡
// 这种情况只需让头节点的左孩子成为头节点      头节点成为头节点左孩子的右节点  然后把摘下的节点  重新挂
//在 原来的头节点的左边(即成为左孩子)  

//第二种情况  当头节点的左孩子的右孩子造成树的不平衡
//首先 找到那个造成树不平衡的节点 取下这个节点 让其成为新的头节点  源头节点成为新节点的右节点 源节点的左节点 成为新节点的左节点   这种情形 下面代码中有描述


// 然后右边的情况和左边大概相同 (不在简诉)  以上简绍是总体思路 还有一些细节 这里不在叙述
//本片只是实现了 平衡二叉树的插入算法和测试  其他的增删查改是没有实现 */
#include<stdio.h>
#include<malloc.h>
typedef struct Tree
{
	int data;//这是所要存储的数据
	Tree *Lp, *Rp;//右 左 孩子
}Tree;

int LeftSumB(Tree*p);
int RightSumB(Tree*p);

Tree* CreateTree(int data)
{
	Tree*temp = (Tree*)malloc(sizeof(Tree));
	temp->data = data; temp->Lp = NULL; temp->Rp = NULL;
	return temp;
}

int LeftSumA(Tree*p)
{
	return LeftSumB(p->Lp);
}

int LeftSumB(Tree*p)
{
	int tempA = 0, tempB = 0;
	if (p == NULL) { return tempA; }
	if (p->Lp == NULL && p->Rp == NULL) { return ++tempA; }
	if (p->Lp != NULL && p->Rp != NULL)
	{
		tempA = LeftSumB(p->Lp); tempA++;
		tempB = LeftSumB(p->Rp);
		return tempA + tempB;
	}
	if (p->Lp != NULL && p->Rp == NULL)
	{
		tempA = LeftSumB(p->Lp);
		return ++tempA;
	}
	if (p->Lp == NULL && p->Rp != NULL)
	{
		tempA = LeftSumB(p->Rp);
		return ++tempA;
	}
}

int RightSumA(Tree*p)
{
	return RightSumB(p->Rp);
}

int RightSumB(Tree*p)
{
	int tempA = 0, tempB = 0;
	if (p == NULL) { return tempA; }
	if (p->Lp == NULL && p->Rp == NULL) { return ++tempA; }
	if (p->Lp != NULL && p->Rp != NULL)
	{
		tempA = RightSumB(p->Lp); tempA++;
		tempB = RightSumB(p->Rp);
		return tempA + tempB;
	}
	if (p->Lp != NULL && p->Rp == NULL)
	{
		tempA = RightSumB(p->Lp);
		return ++tempA;
	}
	if (p->Lp == NULL && p->Rp != NULL)
	{
		tempA = RightSumB(p->Rp);
		return ++tempA;
	}
}

Tree* GetFather(Tree*p, int data)
{
	if (p == NULL) { return false; }
	if (p->Lp == NULL && p->Rp == NULL) { return false; }
	if (p->Lp != NULL)
	{
		if (p->Lp->data == data)
		{
			return p;
		}
	}
	if (p->Rp != NULL)
	{
		if (p->Rp->data == data)
		{
			return p;
		}
	}
	if (p->data > data) { return GetFather(p->Lp, data); }
	if (p->data < data) { return GetFather(p->Rp, data); }
}
Tree*FindNode(Tree*p, int data)
{
	if (p == NULL) { return NULL; }
	if (p->data == data) { return p; }
	if (p->data > data) { return FindNode(p->Lp, data); }
	if (p->data < data) { return FindNode(p->Rp, data); }
}
int GetLeftDeep(Tree*p)
{
	int tempA = 0, tempB = 0;
	if (p == NULL) { return tempA; }
	if (p->Lp == NULL && p->Rp == NULL) { return ++tempA; }
	if (p->Lp != NULL && p->Rp == NULL) { tempA = GetLeftDeep(p->Lp); return ++tempA; }
	if (p->Rp != NULL && p->Lp == NULL) { tempA = GetLeftDeep(p->Rp); return  ++tempA; }
	if (p->Lp != NULL && p->Rp != NULL)
	{
		tempA = GetLeftDeep(p->Lp);
		tempB = GetLeftDeep(p->Rp);
		if (tempA >= tempB) { return ++tempA; }
		else
		{
			return ++tempB;
		}
	}
}
int GetRightDeep(Tree*p)
{
	int tempA = 0, tempB = 0;
	if (p == NULL) { return tempA; }
	if (p->Lp == NULL && p->Rp == NULL) { return ++tempA; };
	if (p->Lp != NULL && p->Rp == NULL) { tempA = GetRightDeep(p->Lp); return ++tempA; }
	if (p->Rp != NULL && p->Lp == NULL) { tempA = GetRightDeep(p->Rp); return  ++tempA; }
	if (p->Lp != NULL && p->Rp != NULL)
	{
		tempA = GetRightDeep(p->Rp);
		tempB = GetRightDeep(p->Lp);
		if (tempA >= tempB)
		{
			return ++tempA;
		}
		else
		{
			return ++tempB;
		}
	}
}
bool MakeTreeIsBalance(Tree*&p, int data, int where)
{
	if (where == -1)//说明是左边不平衡了
	{
		//情况1  当插入节点的数值是小于根节点左边第一个节点的数值
		if (p->Lp->data > data)
		{
			Tree*temp = p->Lp->Rp;
			p->Lp->Rp = p;
			p = p->Lp;
			p->Rp->Lp = temp;
			return true;
		}
		if (p->Lp->data < data)
		{
			Tree*tempA = GetFather(p, data);
			Tree*tempB = FindNode(p, data);  // 找到造成树不平衡的那个点
			if (tempA->Lp != NULL)//说明该节点是 父节点的左节点 清除其数据 让其不要在指向新的头节点
			{
				tempA->Lp = NULL;
			}
			if (tempA->Rp != NULL)//说明该节点是 父节点的右节点 清除其数据 让其不要在指向新的头节点
			{
				tempA->Rp = NULL;
			}
			tempB->Rp = p;//  原头节点 成为新节点的右节点
			tempB->Lp = p->Lp;// 原头节点的左节点 成为新节点的左节点
			p = tempB;// 把头节点换成造成不平衡的点
			p->Rp->Lp = NULL; //清除原头节的左节点数据 因为在旋转后 该节点已经没有数据
			return true;
		}
	}
	if (where == 1)//说明是右边不平衡了
	{
		if (p->Rp->data < data)
		{
			Tree*temp = p->Rp->Lp;
			p->Rp->Lp = p;
			p = p->Rp;
			p->Lp->Rp = temp;
			return true;
		}
		if (p->Rp->data > data)
		{
			Tree*tempA = GetFather(p, data);
			Tree*tempB = FindNode(p, data);
			if (tempA->Lp != NULL) { tempA->Lp = NULL; }
			if (tempA->Rp != NULL) { tempA->Rp = NULL; }
			tempB->Rp = p->Rp;
			tempB->Lp = p;
			p = tempB;
			p->Lp->Rp = NULL;
			return true;
		}
	}
}
int InsertNodeA(Tree*&p, int data)
{
	Tree*temp = NULL;
	int is;
	if (p == NULL) { is = false;   return is; }
	if (p->data == data) { is = false;  return is; }
	//情况1
	if (p->Lp != NULL && p->Rp != NULL)
	{
		if (p->data > data) { return InsertNodeA(p->Lp, data); }
		if (p->data < data) { return InsertNodeA(p->Rp, data); }
	}
	//情况二
	if (p->Lp == NULL && p->Rp == NULL)
	{
		temp = (Tree*)malloc(sizeof(Tree));
		temp->Lp = NULL; temp->Rp = NULL; temp->data = data;
		if (p->data > data) { p->Lp = temp; }
		if (p->data < data) { p->Rp = temp; }
		is = true; return is;
	}
	//情况三
	if (p->Lp != NULL && p->Rp == NULL)
	{
		temp = (Tree*)malloc(sizeof(Tree));
		temp->data = data; temp->Lp = NULL; temp->Rp = NULL;
		if (p->data < data)
		{
			p->Rp = temp;
		}
		else
		{//这种情况进行旋转
			if (p->Lp->data > data)
			{
				p->Lp->Lp = temp;
				p->Lp->Rp = p;
				p = p->Lp;
				p->Rp->Lp = NULL; p->Rp->Rp = NULL;
			}
			else
			{
				temp->Lp = p->Lp;
				temp->Rp = p;
				p = temp;
				p->Rp->Lp = NULL; p->Rp->Rp = NULL;
			}
		}
		is = true; return is;
	}
	//情况四
	if (p->Lp == NULL && p->Rp != NULL)
	{
		temp = (Tree*)malloc(sizeof(Tree));
		temp->data = data; temp->Lp = NULL; temp->Rp = NULL;
		if (p->data > data)
		{
			p->Lp = temp;
		}
		else
		{//这种情况进行旋转
			if (p->Rp->data < data)
			{
				p->Rp->Lp = p;
				p->Rp->Rp = temp;
				p = p->Rp;
				p->Lp->Lp = NULL; p->Lp->Rp = NULL;
			}
			else
			{
				temp->Lp = p;
				temp->Rp = p->Rp;
				p = temp;
				p->Lp->Lp = NULL; p->Lp->Rp = NULL;
			}
		}
		is = true; return is;
	}
}
bool InsertNode(Tree*&p, int data)
{
	int tempA = 0, tempB = 0;
	int where = 0;//主要是看那边已经出现了不平衡  -1是左边多了 1是右边多了
	if (InsertNodeA(p, data))
	{//插入成功
		tempA = GetLeftDeep(p->Lp);
		tempB = GetRightDeep(p->Rp);
		if (tempA - tempB > 1 || tempB - tempA > 1)
		{//说明已经不平衡 要调整

			if (tempA - tempB > 1) { where = -1; }
			if (tempB - tempA > 1) { where = 1; }
			return   MakeTreeIsBalance(p, data, where);
		}
		else {
			return true;//平衡 
		}
	}
	else {
		return false;
	}
}

void ShowNode(Tree*p)
{
	if (p == NULL) { return; }
	ShowNode(p->Lp);
	printf("%d   ", p->data);
	ShowNode(p->Rp);
}
int main()
{
	Tree*temp = CreateTree(10);
	InsertNode(temp, 2);
	InsertNode(temp, 13);
	InsertNode(temp, 3);
	InsertNode(temp, 5);
	InsertNode(temp, 6);
	InsertNode(temp, 7);
	InsertNode(temp, 12);
	InsertNode(temp, 15);
	InsertNode(temp, 11);
	InsertNode(temp, 145);
	InsertNode(temp, 123);
	InsertNode(temp, -12);
	InsertNode(temp,98);
	InsertNode(temp,-18);
	InsertNode(temp,892);
	InsertNode(temp,722);
	InsertNode(temp,-14);
	InsertNode(temp,271);
	InsertNode(temp,0);
	InsertNode(temp,-27);
	printf("%d\n", GetLeftDeep(temp->Lp));
	printf("%d\n",GetRightDeep(temp->Rp));
    printf("\n"); 	ShowNode(temp);
}
//这时 测试结果!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值