查找树-----平衡二叉树

#include <stdio.h>
#include<stdlib.h>

#define  Ok 1
#define  Error 0
#define max 20
#define Status int 
#define LH 1
#define EH 0
#define RH -1
typedef struct Btree{
    Btree *lchild;
    Btree *rchild;
    int   data;
    int bf;//用来记录该节点所处的状态0,1或-1
}Btree,*Bitree;//平衡二叉树节点的结构体
/*Btree *creattree(Bitree &b)//用来创建二叉树的,但是算法中有从根节点创建的语句,所以这一步就省略了
{
    int ch1;
    scanf("%d",&ch1);
    if(ch1==0)
        b=NULL;
    else
    {
        b=(Btree*)malloc(sizeof(Btree));
        if(!b)  exit(1);
        b->data=ch1;
        printf("请输入%d的左节点",b->data);
        b->lchild=creattree(b->lchild);
        printf("请输入%d的右节点",b->data);
        b->rchild=creattree(b->rchild);
    }
    return b;
}*/
Status inital(Bitree &b)//初始化树
{
    b=(Btree*)malloc(sizeof(Btree));//不先初始化给树一个地址的话,在主函数里b是传递不进去的,会报错
    b=NULL;
    return 1;
}
bool  EQ(int i,int j)
{
   if(i==j)
       return 1;
   else 
       return 0;
}
bool LT(int i,int j)
{
    if(i<j)
        return 1;
    else 
        return 0;
}
void R_Rotate(Bitree &p)//单项右旋处理
{
    Bitree lc;
    lc=p->lchild; //需要将p与他的左孩子节点旋转
    p->lchild=lc->rchild;//将左孩子的右节点给根节点做左孩子节点
    lc->rchild=p;//让根节点做它以前左孩子结点的右孩子节点
    p=lc;//转换根节点
}
void L_Rotate(Bitree &p)//单项左旋处理
{
    Bitree lc;
    lc=p->rchild; //道理同上
    p->rchild=lc->lchild;
    lc->lchild=p;
    p=lc;
}
void leftBalance(Bitree &t)//当以t为根节点已经左子树比右子树多1个高度的情况下再向左子树叶子节点插入一个节点
{
    Bitree lc,rd;
    lc=t->lchild;
    switch(lc->bf){//查看插入后t的左孩子的状态
    case LH://如果插入后左子树比右子树高
        t->bf=lc->bf=EH;//重置t和他左子树的状态
        R_Rotate(t);//进行单向右旋处理
        break;
    case RH://如果插入后右子树比左子树高,须进行双旋处理
        rd=lc->rchild;
        switch(rd->bf)//这一步得根据分析的图来进行旋转后的赋值
        {
       case LH:
           t->bf=RH; lc->bf=EH;
        break;
       case RH:
           t->bf=EH; lc->bf=LH;
           break;
       case EH:
           t->bf=lc->bf=EH;
           break;
        }
        break;
        rd->bf=EH;
       L_Rotate(t->lchild);//先对t的左孩子节点做单向做平衡处理
       R_Rotate(t);//再对t做单向右平衡处理
    }
}
void RightBalance(Bitree &t)//当以t为根节点已经右子树比左子树多1个高度的情况下再向右子树叶子节点插入一个节点
{
    Bitree rc,ld;
    rc=t->rchild;
    switch(rc->bf)
    {
    case RH:
        rc->bf=t->bf=EH;
        L_Rotate(t);
        break;               //同上
    case LH:
        ld=rc->lchild;
        switch(ld->bf)
        {
        case RH:  t->bf=LH; rc->bf=EH;
            break;
        case LH:   t->bf=EH; rc->bf=RH;
            break;
        case EH:   t->bf=rc->bf=EH;
            break;
        }
        ld->bf=EH;
        R_Rotate(t->rchild);
        L_Rotate(t);
        break;
    }
}
Status InsertAVL(Bitree &t,int e,bool &taller)//插入平衡二叉树的节点函数
{
    if(!t){                              //插入节点成功
      t=(Bitree)malloc(sizeof(Btree));
      t->data=e;  t->lchild=t->rchild=NULL; 
      t->bf=EH;   taller=true;
    }
    else {
        if(EQ(e,t->data))   //如果插入的节点在树中已经是存在的了,那么不用查了,
        {taller=false; return 0;}
        if(LT(e,t->data))//如果插入的节点是在左子树中
        {
            if(!InsertAVL(t->lchild,e,taller))  return 0;//一直递归到要插入的叶子节点的位置
            if(taller)//如果成功插入一个叶子节点,需要看它是否符合平衡二叉树要求,再修改
            {
                switch(t->bf)
                {
                case LH://如果它的父节点在插入前就是左子树比右子树大的话
                    leftBalance(t);  taller=false;  //当以t为根节点已经左子树比右子树多1个高度的情况下再向左子树叶子节点插入一个节点
                    break;
                case EH://如果它的父节点在插入前就是左子树与右子树高度相等时
                    t->bf=LH;  taller=true; //记录父节点左子树比右子树高1
                    break;
                case RH://如果它的父节点在插入前就是左子树比右子树小1的话
                    t->bf=EH;  taller=false;//此时父节点左右子树相等
                    break;
                }
            }
        }
        else {  //当插入的节点在右子树的话。。。。。道理同上
                if(!InsertAVL(t->rchild,e,taller))  return 0;
                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 1;
}
Status Showtree(Bitree t)
{
    if(t)
    {
        if(Showtree(t->lchild))
        {
            printf("%d\n",t->data);
            if(Showtree(t->rchild))
                return Ok;
        }
    }
    else return Ok;
}
void main()
{
    Bitree t;
    int e;  bool taller;
    /*printf("请输入根节点");
    creattree(t);*/
   inital(t); 
    printf("请输入要插入的节点(输入0结束)");
    scanf("%d",&e);
    while(e!=0)
    {
     InsertAVL(t,e,taller);
     scanf("%d",&e);
    }
    printf("平衡二叉树的中序序列为:\n");
    Showtree(t);
    getchar();
    getchar();
}
//算法分析:1.平衡二叉树的要求:(1)它的左右子树都是平衡二叉树(2)它的左右子树的深度只差的绝对值不超过1
           //2.在平衡二叉树上进行查找过程和排序树相同,进行比较的关键字个数不超过树的深度
          //3.进行查找的时间复杂度为O(logn)

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/q270274978/article/details/8484952
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞