怎么说呢,我刚开始对于这个平衡树简直无计可施,但是学长讲了之后,问了几个问题,感觉有问题主要是以下几个地方:
- 树高怎么记录(其实也不算什么大问题)
- 旋转的时候,结点以及结点的孩子是怎么操作的
- 建树的时候对于是否失衡的判断
下面贴代码
PS:本人外语是小语种,自定义函数基本是汉语拼音的缩写,比较尴尬
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
int data;
int h;
struct node *l, *r;
};
int geth(struct node *root) //获取结点的树高
{
if(root)
return root->h;
else
return -1;
}
struct node* ll(struct node *root) //左左结构旋转,即造成失衡的结点在失衡结点的左子树的左子树上
{
struct node *p;
p = root->l;
root->l = p->r;
p->r = root;
root->h = geth(root->l) > geth(root->r) ? geth(root->l) + 1 : geth(root->r) + 1;
p->h = geth(p->l) > geth(p->r) ? geth(p->l) + 1 : geth(p->r) + 1;
return p;
};
struct node* rr(struct node *root) //右右结构旋转,与左左同理
{
struct node *p;
p = root->r;
root->r = p->l;
p->l = root;
root->h = geth(root->l) > geth(root->r) ? geth(root->l) + 1 : geth(root->r) + 1;
p->h = geth(p->l) > geth(p->r) ? geth(p->l) + 1 : geth(p->r) + 1;
return p;
};
struct node* lr(struct node *root) //左右结构旋转,在失衡结点的左结点进行右右旋转,然后在失衡的结点进行左左旋转
{
root->l = rr(root->l);
return ll(root);
};
struct node* rl(struct node *root)//右左结构旋转,在失衡结点的右结点进行左左旋转,然后在失衡的结点进行右右旋转
{
root->r = ll(root->r);
return rr(root);
};
struct node* js(struct node *root, int a) //建立平衡二叉树
{
if(root == NULL) //如果结点为空,则分配空间,再对其中的值进行初始化
{
root = (struct node*)malloc(sizeof(struct node));
root->data = a;
root->h = 0;
root->l = NULL;
root->r = NULL;
}
else //如果不空
{
if(a > root->data) //如果a大于当前结点的值
{
root->r = js(root->r, a); //进入右子树
if(geth(root->l) - geth(root->r) == -2) //如果右子树过高(平衡被破坏)
{
if(a > root->r->data) //判断失衡结构,进行相应的旋转
{
root = rr(root);
}
else
{
root = rl(root);
}
}
}
else
{
root->l = js(root->l, a); //进入左子树
if(geth(root->l) - geth(root->r) == 2) //如果左子树过高(平衡被破坏)
{
if(a > root->l->data) //判断失衡结构,进行相应旋转
{
root = lr(root);
}
else
{
root = ll(root);
}
}
}
}
root->h = geth(root->l) > geth(root->r) ? geth(root->l) + 1 : geth(root->r) + 1; //更新结点树高
return root; //返回结点
};
int main()
{
int n, m, i;
struct node *root = NULL;
scanf("%d", &n);
for(i = 0;i < n;i++)
{
scanf("%d", &m);
root = js(root, m); //建立树
}
printf("%d\n", root->data); //输出树根的值
return 0;
}
对于LL型,RR型,LR型,RL型,由于能力有限,建议参考这篇文章