// 不是 很会用图片来进行描述我的插入想法 在这里只能简单口述一下
// 最核心的想法就是 始终以最上面的三个节点来调整二叉树 让其达到平衡
//情况分为四种
//第一种 当头节点的左节点的左节点造成了树的不平衡
// 这种情况只需让头节点的左孩子成为头节点 头节点成为头节点左孩子的右节点 然后把摘下的节点 重新挂
//在 原来的头节点的左边(即成为左孩子)
//第二种情况 当头节点的左孩子的右孩子造成树的不平衡
//首先 找到那个造成树不平衡的节点 取下这个节点 让其成为新的头节点 源头节点成为新节点的右节点 源节点的左节点 成为新节点的左节点 这种情形 下面代码中有描述
// 然后右边的情况和左边大概相同 (不在简诉) 以上简绍是总体思路 还有一些细节 这里不在叙述
//本片只是实现了 平衡二叉树的插入算法和测试 其他的增删查改是没有实现 */
#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);
}
//这时 测试结果!
不用平衡因子及父节点来实现平衡二叉树
最新推荐文章于 2025-04-01 14:31:03 发布