目录前言一、平衡二叉树实现原理二、平衡二叉树实现算法三、全部代码前言 对于一个二叉排序树而言 它们的结构都是根据了二叉树的特性从最左子树开始在回到该结点上继续往右结点走
对于一个二叉排序树而言
那么我们通过二叉排序树的展示,会展示成如图:
可以发现,如果我们想通过二叉排序树这个深度为8的树来查找某个数
我们需要走到最后,这是最坏的打算
但是如果我们能将该树改变为平衡二叉树,如图所示:
相比之下我们这个深度为4的平衡二叉树在通过查询值时是效率很平均且稳定的,
那么通过上面的问题我们该怎么将这个二叉排序树的变成平衡二叉树是我们现在的问题了。
对于平衡二叉树的特性而言,我们在上面也有举例到
而我们该如何去计算该二叉排序树的平衡因子(平衡因子 = 左子树 - 右子树的值)呢?
我们可以结合上面那个最坏打算的二叉排序树的生成方式进行逐一分析。
如图:
可以看到当我们单步调试二叉排序树的时候到值1的时候值3的平衡因子为2>1
那么此时并不符合我们的平衡二叉树的规则
那么我们需要通过某种形式去调换,使其符合我们的平衡二叉树的规则
而图2就是由图1通过顺时针而得到出来的,在这里我们称为右旋
之后我们的值4继续插入,因为值4>值3,所以根据二叉排序树的特性是值3的右子树
那么也没出现什么问题之后继续插入下一个值5,因为值5>值4,所以值5会到值4的右子树上。
如图所示:
可以发现图4中当插入值5的时候,根节点、值3的平衡因子的绝对值=2
剩下就不多去演示了,整体是一个递归的过程
要想深刻了解平衡二叉树的实现原理请自行参考程杰著作的《大话数据结构》。
在类型上我们会通过二叉排序树的基础上添加一个bf,用于存储平衡因子,而定义了一个Status则是判断当前状态的代码。
代码如下:
typedef int Status;
typedef struct BiTnode
{
int data;
int bf;
struct BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
为了方便理解,我们前面的提到的左旋和右旋的方式,在C语言的代码中该如何实现呢?下面我们就来将代码展示出来。
代码如下:
void R_Rotate(BiTree* P)
{
BiTree L;
L = (*P)->lchild;
(*P)->lchild = L->rchild;
L->rchild = (*P);
*P = L;
}
void L_Rotate(BiTree* P)
{
BiTree R;
R = (*P)->rchild;
(*P)->rchild = R->lchild;
R->lchild = (*P);
*P = R;
}
我们可以看到左旋和右旋的代码很类似,所以我们通过了解了右旋的代码的含义自然就可以反推出左旋的含义了。
此函数的意思是:
如果文字还不了解我们可以将上述图1、图2的图片进行推导。
如图:
那么左旋的操作就是一个逆时针的方向转换,代码也是类似这里就不再演示了。
现在我们来看左平衡旋转处理的代码函数:
#define LH +1
#define EH 0
#define RH -1
void RightBalance(BiTree* T)
{
BiTree R, Rl;
R = (*T)->rchild;
switch (R->bf)
{
case RH:
(*T)->bf = R->bf = EH;
L_Rotate(T);
break;
case LH:
Rl = R->lchild;
switch (Rl->bf)
{
case RH: (*T)->bf = LH;
R->bf = EH;
break;
case EH: (*T)->bf = R->bf = EH;
break;
case LH: (*T)->bf = EH;
R->bf = RH;
break;
}
Rl->bf = EH;
R_Rotate(&(*T)->rchild);
L_Rotate(T);
}
}
void LeftBalance(BiTree* T)
{
BiTree L, Lr;
L = (*T)->lchild;
switch (L->bf)
{
case LH:
(*T)->bf = L->bf = EH;
R_Rotate(T);
break;
case RH:
Lr = L->rchild;
switch (Lr->bf)
{
case LH: (*T)->bf = RH;
L->bf = EH;
break;
case EH: (*T)->bf = L->bf = EH;
break;
case RH: (*T)->bf = EH;
L->bf = LH;
break;
}
Lr->bf = EH;
L_Rotate(&(*T)->lchild);
R_Rotate(T);
}
}
如图:
首先通过代码可以看到,我们定义了三个常数变量,分别代码1、0、-1。
然后呢因为是左平衡旋转处理我们需要获取当前图片所示的P结点(也就是我之前假设的根节点的顶点)的左子树,
这里要注意重点:
#include "stdio.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 100
typedef int Status;
typedef struct BiTNode
{
int data;
int bf;
struct BiTNode* lchild, * rchild;
} BiTNode, * BiTree;
void R_Rotate(BiTree* P)
{
BiTree L;
L = (*P)->lchild;
(*P)->lchild = L->rchild;
L->rchild = (*P);
*P = L;
}
void L_Rotate(BiTree* P)
{
BiTree R;
R = (*P)->rchild;
(*P)->rchild = R->lchild;
R->lchild = (*P);
*P = R;
}
#define LH +1
#define EH 0
#define RH -1
void LeftBalance(BiTree* T)
{
BiTree L, Lr;
L = (*T)->lchild;
switch (L->bf)
{
case LH:
(*T)->bf = L->bf = EH;
R_Rotate(T);
break;
case RH:
Lr = L->rchild;
switch (Lr->bf)
{
case LH: (*T)->bf = RH;
L->bf = EH;
break;
case EH: (*T)->bf = L->bf = EH;
break;
case RH: (*T)->bf = EH;
L->bf = LH;
break;
}
Lr->bf = EH;
L_Rotate(&(*T)->lchild);
R_Rotate(T);
}
}
void RightBalance(BiTree* T)
{
BiTree R, Rl;
R = (*T)->rchild;
switch (R->bf)
{
case RH:
(*T)->bf = R->bf = EH;
L_Rotate(T);
break;
case LH:
Rl = R->lchild;
switch (Rl->bf)
{
case RH: (*T)->bf = LH;
R->bf = EH;
break;
case EH: (*T)->bf = R->bf = EH;
break;
case LH: (*T)->bf = EH;
R->bf = RH;
break;
}
Rl->bf = EH;
R_Rotate(&(*T)->rchild);
L_Rotate(T);
}
}
Status InsertAVL(BiTree* T, int e, Status* taller)
{
if (!*T)
{
*T = (BiTree)malloc(sizeof(BiTNode));
(*T)->data = e; (*T)->lchild = (*T)->rchild = NULL; (*T)->bf = EH;
*taller = TRUE;
}
else
{
if (e == (*T)->data)
{
*taller = FALSE; return FALSE;
}
if (e < (*T)->data)
{
if (!InsertAVL(&(*T)->lchild, e, taller))
return FALSE;
if (*taller)
switch ((*T)->bf)
{
case LH:
LeftBalance(T); *taller = FALSE; break;
case EH:
(*T)->bf = LH; *taller = TRUE; break;
case RH:
(*T)->bf = EH; *taller = FALSE; break;
}
}
else
{
if (!InsertAVL(&(*T)->rchild, e, taller))
return FALSE;
if (*taller)
switch ((*T)->bf)
{
case LH:
(*T)->bf = EH; *taller = FALSE; break;
case EH:
(*T)->bf = RH; *taller = TRUE; break;
case RH:
RightBalance(T); *taller = FALSE; break;
}
}
}
return TRUE;
}
int main(void)
{
int i;
int a[10] = { 3,2,1,4,5,6,7,10,9,8 };
BiTree T = NULL;
Status taller;
for (i = 0; i < 10; i++)
{
InsertAVL(&T, a[i], &taller);
}
printf("本样例建议断点跟踪查看平衡二叉树结构");
return 0;
}
到此这篇关于如何使用C语言实现平衡二叉树 的文章就介绍到这了,更多相关C语言实现平衡二叉树内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: 如何使用C语言实现平衡二叉树数据结构算法
本文链接: https://www.lsjlt.com/news/133054.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0