平衡二叉树及其操作实现

[问题描述]

    实现平衡二叉排序树的创建、插入、删除、查询操作,并求出所构建平衡二叉排序树的平均查找长度ASL。

[基本要求] 

(1)以二叉链表作为平衡二叉树的存储结构;

(2)输入一个关键字序列,建立对应的平衡二叉树;

(3)向平衡二叉树中插入一个结点(关键字);

(4)从平衡二叉树中删除一个结点(关键字);

(5)计算平衡二叉树的平均查找长度;

(6)销毁平衡二叉树。

计算平衡二叉树的平均查找长度公示(n为结点数):

ALS=((n+1)/n)*(log10(n+1)/log10(2))-1;

 

 

#include<stdio.h>    
#include<stdlib.h> 
#include<math.h>  
#define LH  1  //左高  
#define EH  0  //一样高  
#define RH -1  //右高
#define TRUE   1
#define FALSE  0  
typedef int Status ;
typedef bool Boolean ;
typedef struct BSTNode  
{  
    int data;  
    int bf;       //结点的平衡因子
    struct BSTNode * lchild,* rchild;  //左、右孩子指针 
}BSTNode,*BSTree;


//以*p为根的二叉排序做右旋处理
 void R_Rotate(BSTree &p)
 {
	 BSTree lc=p->lchild ;      //lc指向*p左子树根结点
	 p->lchild =lc->rchild ;    //lc右子树挂接为*p左子树 
	 lc->rchild =p;             //p指向新的根结点
	 p=lc;
 }//R_Rotate

 //以*p为根的二叉排序做左旋处理
 void L_Rotate(BSTree &p)
 {
	 BSTree rc=p->rchild ;     //rc指向*p右子树根结点
	 p->rchild =rc->lchild ;   //rc左子树挂接为*p右子树 
	 rc->lchild =p;            //p指向新的根结点
	 p=rc;
 }//L_Rotate

//  对二叉树T进行左平衡处理(LL型和LR型)  
void LeftBalance(BSTree &T)   
{  
    BSTree lc = T->lchild;  
    switch (lc->bf)   
    {  
        //LL型的只需要进行右旋操作  
    case LH:  
        //右旋之后根和左子树都的平衡的  
        T->bf=lc->bf = EH; 
        R_Rotate(T);  //右旋操作 
        break;  
        //LR型的需要进行左旋操作,然后右旋操作  
    case RH:  
        BSTree rd = lc->rchild;  
        switch (rd->bf)   
        {  //修改*T及其左孩子的平衡因子
        case LH:T->bf = RH;  lc->bf = EH;break;     
        case EH:T->bf = EH;  lc->bf = EH;break;
        case RH:T->bf = EH;  lc->bf = LH;break;        
        }  //switch (rd->bf)
        rd->bf = EH;  
        L_Rotate(T->lchild);  
        R_Rotate(T);  
        break;  
    }  //switch (lc->bf)
}  //LeftBalance

void RightBalance(BSTree & T)   
{  
    BSTree rc = T->rchild;  
    switch (rc->bf)   
    {  
        //RR型只需要做左旋操作  
    case RH:  
        T->bf = EH;  
        rc->bf = EH;  
        L_Rotate(T);  //左旋操作
        break;  
        //RL型需要先做右旋操作,然后做左旋操作  
    case LH:  
        BSTree ld = rc->lchild;  
        switch (ld->bf)   
        {  
        case LH:T->bf = EH;  rc->bf = RH;break;
        case EH:T->bf = EH;  rc->bf = EH;break;        
        case RH:T->bf = LH;  rc->bf = EH;break;        
        } //switch (ld->bf) 
        ld->bf = EH;  
        R_Rotate(T->rchild);  
        L_Rotate(T);  
        break;  
    }//switch (rc->bf)  
} //RightBalance

//把元素e插入平衡二叉树T中  
Status InsertAVL(BSTree &T, int e, Boolean & taller)   
{  
    if (!T)   
    {  
        T = (BSTree)malloc(sizeof(BSTNode));  
        T->rchild = NULL;  
        T->lchild = NULL;  
        T->data = e;  
        T->bf = EH;  
        taller = TRUE;  
    }  
    else  
    {  
        //该元素已经在平衡二叉树中存在了  
        if (e == T->data)   
        {  
            taller = FALSE;  
            return FALSE;  
        }  
        //插入左子树  
        else if (e < T->data)   
        {  
            if (!InsertAVL(T->lchild, e, taller))   return FALSE;  //未插入            
            if (taller)   //插入成功,并且树变高了
            {  
                switch (T->bf)   
                {  
                case LH:  
                    LeftBalance(T); taller = FALSE; break;
                    //平衡二叉树做完左平衡操作后  
                    //树高没有变化,故taller = false       
                case EH:  
                    T->bf = LH; taller = TRUE; break;
                    //原来是平衡的故插入一个元素后  
                    //树高必然变高  
                case RH:  
                    T->bf = EH;taller = FALSE; break; 
                    //原来是右子树比左子树高,但是当向左子树中  
                    //插入一个元素的时候,树变平衡了,故taller = false       
                }  //switch (T->bf)
            } //if (taller) 
        }  
        //插入右子树  
        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;  
                } // switch (T->bf)
            }  //if (taller)
        } //else 
    }  //else
    return TRUE;  
}//InsertAVL   

//从平衡二叉树中删除一个结点(关键字)
Status DeleteAVL(BSTree &T, int key, Boolean &shorter)
{  
    if (!T)  
    {//没有关键字  
        shorter = FALSE; 
		printf("该平衡二叉树中无此关键字!\n");
        return 0;  
    }  
    else  
    {  
        if (key==T->data)    //找到了需要删除的结点  
        {  
            //如果该结点的lchild 和  
            //rchild 至少有一个为NULL  
            //则大功告成,否则请参照  
            //下方解释  
            BSTree q = T;  
            if (!T->lchild)//如果该结点的lchild 为NULL  
            {  
                q = T;  
                T = T->rchild;  
                free(q);  
                shorter = TRUE;  
                return TRUE;  
            }  
            else if (!T->rchild){//如果该结点的rchild 为 NULL  
                q = T;  
                T = T->lchild;//如果不是&(引用)的强大功能,这句话是没有意义的  
                free(q);  
                shorter = TRUE;  
                return TRUE;  
            }  
            else {  
                //删除一个左右孩子都不为空的结点  
                //使该结点的直接前驱p的data替换该结点的data  
                //然后改变key=p.data  
                BSTree s = T->lchild;  
                while (s->rchild)  
                    s = s->rchild;  
                T->data = s->data;  
                key = s->data;  
            }  
        }  
        if (key<T->data)
		{  
            if (!DeleteAVL(T->lchild, key, shorter)) return 0;  
            if (shorter)
			{  
                switch(T->bf)
				{  
                case LH:T->bf = EH; shorter = TRUE;break;  
                case EH:T->bf = RH; shorter = FALSE;break;  
                case RH:RightBalance(T);   
                    if (T->rchild->bf == EH)  
                        shorter = FALSE;  
                    else   
                        shorter = TRUE;break;  
                }//switch(T->bf)  
            }  
        }  
        else{  
            if (!DeleteAVL(T->rchild, key, shorter)) return 0;  
            if (shorter)
			{  
                switch(T->bf)
				{  
                case LH:LeftBalance(T);  
                    if (T->lchild->bf == EH)  
                        shorter = FALSE;  
                    else   
                        shorter = TRUE;break;  
                case EH:T->bf = LH; shorter = FALSE;break;  
                case RH:T->bf = EH; shorter = TRUE;break;  
                }  
            }  
        }  
    }  
    return 1;  
}//DeleteAVL  

//计算平衡二叉树的平均查找长度(查找关键字e)
Status SearchBST(BSTree & T, int e)   
{  
    if (T ==NULL)   
    {  
		printf("该平衡二叉树中无此关键字!\n");
        return NULL;  
    }   
    if (T->data == e)   
    {  
        return T->data;  
    }  
    else if (e< T->data)   
    {   
        return SearchBST(T->lchild, e);  
    }   
    else   
    {   
        return SearchBST(T->rchild, e);  
    }  
}  

//销毁平衡二叉树
void DestroyBST(BSTree & T)   
{  
    if (NULL == T) return;  
    DestroyBST(T->lchild);  
    DestroyBST(T->rchild);  
    free(T);  
} 

//输出平衡二叉树中的所有的元素(小->大,中序遍历)  
void PrintBST(BSTree & T)  
{  
    if (NULL == T) return;  
    PrintBST(T->lchild);  
    printf("%d  ",T->data);  
    PrintBST(T->rchild); 
}
  
//7-统计树的叶子结点个数
Status CountLeafs(BSTree T)  
{
int i,j;
   if (T) 
   {
      i=CountLeafs(T->lchild); 
      j=CountLeafs(T->rchild); 
      return i+j+1;
   } 
   else 
	   return 0;
}

//平均查找长度
float ASL(BSTree T)
{
	float n;
	float ALS;
    n=CountLeafs(T);
    ALS=((n+1)/n)*(log10(n+1)/log10(2))-1;
	return ALS;
}


主函数:

 

 

void main()
{
	BSTree T=NULL;
	bool taller = false,shorter;
	int n,a;float c;
	printf("请输入数据 ,输入0结束:\n");
	       while(scanf("%d",&n))  
		   {
		       if(n==0) break;  
	           else  InsertAVL(T,n,taller); 
		   }
		   printf("平衡二叉树建立成功!\n");
		   printf("请输入插入的结点:");
		   scanf("%d",&n);
           InsertAVL(T,n,taller);
		   printf("插入成功!\n");
		   printf("请输入需要删除的结点:");
           scanf("%d",&n);
		   DeleteAVL(T,n,shorter);
		   c=ASL(T);
		   printf("平均查找长度为:\n");
		   printf("ASL=%5.2f\n",c);
		   printf("其结果为:\n");
		   PrintBST(T);
		   printf("\n");
		   DestroyBST(T);
}

 

 

 

 

 

 

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DXnima

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值