我们为了解决二叉树的查找,我们构建出了二叉搜索树(左子树小于其父结点,右子树大于其父结点)。但是这样显然是不够的,这样的查找太过于笨重,我们就想出了二叉平衡树:
就是一个结点的左右子树高度差不能等于2,当等于2时,我们就对它进行平衡,这样减少了极端情况,可以明显的缩小查找的时间,二叉平衡在插入的时候会出现四种情况——LL,RR,LR,RL。下面我们用代码进行说明:
#include <stdio.h>
#include <stdlib.h>
typedef struct TNode {
int data;
struct TNode *left;
struct TNode *right;
int height;
}TNode,*Tree;
typedef struct QNode {
Tree data;
int top;
int base;
int maxsize;
}QNode,*Queue;
void InitQueue (Queue *q);//初始化队列。
void En (Queue q, Tree T);//进队。
Tree De (Queue q);//出队。
int IsFull (Queue q);//判断是否为满。
int IsEmpty (Queue q);//判断是否为空。
void Level (Tree T);//层次遍历二叉树。
void Level (Tree T)//层次遍历是用来检验二叉树是否平衡正确。
{
Queue q;
InitQueue (&q);
En(q,T);
Tree temp;
while(!IsEmpty(q)) {
temp = De(q);
printf("%d ",temp->data);
if(temp->left) En(q,temp->left);
if(temp->right) En(q,temp->right);
}
}
void InitQueue (Queue *q)
{
(*q) = (QNode*) malloc(sizeof(QNode));
(*q)->top = (*q)->base = 0;
(*q)->maxsize = 10;
(*q)->data = (Tree) malloc(sizeof(TNode) * (*q)->maxsize);
}
int IsFull(Queue q)
{
return ((q->top + 1) % (q->maxsize - 1) == q->base);
}
int IsEmpty (Queue q)
{
return (q->base == q->top);
}
void En (Queue q, Tree T)
{
if (IsFull(q)) {
printf("The queue is full!
");
}else {
TNode *temp;
temp = T;
q->data[q->top] = *temp;
q->top = (q->top + 1) % (q->maxsize -1 );
}
}
Tree De (Queue q)
{
if(IsEmpty(q)) {
printf("The queue is empty!
");
}else {
Tree T;
T = &(q->data[q->base]);
q->base = (q->base + 1) % (q->maxsize - 1);
return T;
}
}
int Height (Tree T)//返回当前结点的高度。
{
if(!T) {
return -1;
}else {
return T->height;
}
}
int Max (int a, int b)//返回a,b中最大的数字
{
return a>b?a:b;
}
Tree RotateWithLeft (Tree T)//左旋转来平衡该结点。
{
Tree temp;
temp = T->left;
T->left = temp->right;
temp->right = T;
T->height = Max(Height(T->left),Height(T->right)) + 1;
temp->height = Max (Height(temp->left),Height(temp->right)) + 1;
return temp;
}
Tree RotateWithRight (Tree T)//右旋转平衡该结点。
{
Tree temp;
temp = T->right;
T->right = temp->left;
temp->left = T;
T->height = Max(Height(T->left),Height(T->right)) + 1;//更新T的高度。
temp->height = Max(Height(temp->left),Height(temp->right)) + 1;//更系temp结点的高度。
return temp;
}
Tree RotateWithLeftRight (Tree T)//左右旋转平衡。
{
T->left = RotateWithRight(T->left);
return (RotateWithLeft(T));
}
Tree RotateWithRightLeft (Tree T)//RL旋转平衡。
{
T->right = RotateWithLeft (T->right);
return RotateWithRight(T);
}
Tree Insert (int x, Tree T)
{
if (!T) {//若结点为空,则生成新结点。
T = malloc(sizeof(TNode));
T->data = x;
T->height = 0;
T->left = T->right = NULL;
}else if (x < T->data) {//小于的话,则插入左子树。
T->left = Insert (x,T->left);
if (Height(T->left) - Height(T->right) == 2) {//插入后,若左右子树的高度差等于2,则进行平衡。
if (x < T->left->data) {//若小于,肯定属于LL旋转。
T = RotateWithLeft (T);
}else {//否则属于LR旋转。
T = RotateWithLeftRight(T);
}
}
}else if (x > T->data) {//大于就插入右子树。
T->right = Insert (x,T->right);
if (Height(T->right) - Height(T->left) == 2){
if (x > T->right->data) {//若大于,同上。
T = RotateWithRight(T);
}else {
T = RotateWithRightLeft(T);//同上。
}
}
}
T->height = Max(Height(T->left),Height(T->right)) + 1;//完成后,我们需要更新该结点的高度。
return T;
}
int main ()//测试函数。
{
Tree T;
int i;
for( i =1 ;i < 10;i++) {
T = Insert (i,T);
//printf("data is %d",T->data);
}
Level (T);
return 0;
}
今天就写到这里吧,期待下一次!