数据结构实验--平衡二叉树操作的演示

一、题目描述

利用平衡二叉树实现一个动态查找表,实现动态查找表的三种基本功能:查找、插入和删除。

二、需求分析

1.建立平衡二叉树并进行创建、查找、插入、删除等功能。

2.设计一个实现平衡二叉树的程序,可进行创建、查找、插入、删除等操作,实现动态的输入数据,实时的输出该树结构。

3.测试数据:自选数据

三、概要设计

1.抽象数据类型定义:

typedef struct BSTNode {

int data;    

        int bf;                         //节点的平衡因子

         structBSTNode *lchild,*rchild;    //左右孩子指针

}BSTNode,*BSTree;

 

voidCreatBST(BSTree &T);        //创建平衡二叉树

voidR_Rotate(BSTree &p);         //对以*p为根的二叉排序树作左旋处理

voidL_Rotate(BSTree &p);         //对以*p为根的二叉排序树作左旋处理

voidLeftBalance(BSTree &T);      //对以指针T所指结点为根的二叉树作左平衡旋转处理

voidRightBalance(BSTree &T);    //对以指针T所指结点为根的二叉树作右平衡旋转处理

boolInsertAVL(BSTree &T,int e,bool &taller);          //插入结点e

boolSearchBST(BSTree &T,int key);                 //查找元素key是否在树T中

void LeftBalance_div(BSTree &p,int&shorter);        //删除结点时左平衡旋转处理

void RightBalance_div(BSTree &p,int&shorter);       //删除结点时右平衡旋转处理

void Delete(BSTreeq,BSTree  &r,int &shorter);       //删除结点

int DeleteAVL(BSTree &p,int x,int&shorter);          //平衡二叉树的删除操作

void PrintBST(BSTree T,int m);                     //按树状打印输出二叉树的元素

 

2.主程序的流程

 

请输入操作的选项编号(1-5)

 

1—创建平衡二叉树

2—查找

3—插入

4—删除

5—结束

 

3.各模块之间的层次调用

四、详细设计

1.以平衡二叉树的插入和平衡化为例:

bool InsertAVL(BSTree &T,int e,bool&taller)

{

//若存在平衡的二叉排序树T中不存在和e有相同关键字的节点,则插入一个数据元素为e

//的新结点,并返回1,否者返回0。若因插入而使二叉排序树失去平衡,则作平衡旋转理,

//布尔变量taller反映T长高与否。

    if(!T)//插入新结点,树“长高”,置taller为true

    {

        T = (BSTree)malloc(sizeof(BSTNode));

        T->data = e;

        T->lchild = T->rchild =NULL;

        T->bf = EH; taller = true;

    }

    else

    {

        if(EQ(e,T->data))                 //树中已存在和有相同关键字的结点

        { taller = false;printf(“已存在相同关键字的结点\n”); return 0; }//则不再插入

        if(LT(e,T->data))                 //应继续在*T的左子树中进行搜索

        {

           if(!InsertAVL(T->lchild,e,taller)) return 0;//未插入

            if(taller)                    //已插入到*T的左子树中且左子树“长高”

                switch(T->bf)             //检查*T的平衡度

         {

                  case LH:                //原本左子树比右子树高,需要作左平衡处理

                      LeftBalance(T); taller =false; break;

                  case EH:                //原本左子树、右子等高,现因左子树增高而使树增高

                      T->bf = LH; taller =true; break;

                  case RH:                //原本右子树比左子树高,现左、右子树等高

                      T->bf = EH; taller =false; break;

            }//switch(T->bf)

        }//if

        else                              //应继续在*T的右子树中进行搜索

        {

            if(!InsertAVL(T->rchild,e,taller))return 0;//未插入

            if(taller)                    //已插入到*T的右子树中且右子树“长高”

                switch(T->bf)             //检查*T的平衡度

                                                                                  {

                   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)

        }//else

   }//else

   return 1;

}//InsertAVL

2.说明:执行完输入函数后,会在键盘缓冲区中保存回车键,后面再对字符型量

赋值时,会将缓冲区当成数据存入变量中,所以要在某些输入语句后面加getchar

函数。

五、调试分析

1. 遇到的问题

(1)对平衡二叉树的删除的算法设计程序存在很大问题。删除节点后需要对新的排序树平衡化,改变节点的信息,使之形成一棵新的平衡二叉树。

(2)主函数中的实参和子函数中的实参相等,造成调用该子函数时,虽然没有错误,但其功能不能正确的实现。改变该变量后程序成功实现各种功能。

(3)一些逻辑逻辑运算符书写不正确,造成实现的功能不正确或程序死循环。

六、用户使用说明

1.了解程序清单上给出的功能,并根据提示依次进行操作。

2.创建二叉树,输入的数据元素为整数,当输入-123时,停止创建。并显示平衡二叉树的中序凹入树形图。

3.查找(输入你要查找的元素)。

4.插入(输入要插入的数据元素,并输出)

5.删除(删除指定的元素,并输出)

6.结束

说明:其中每一个功能实现后都会提示是否继续:选择y继续,否则,终止。

 

七、总结

经过这次课程设计实验,我体会到只有保持耐心,坚持到底才有可能做好事情。这次课程设计加强了我动手解决问题的能力,巩固和加深了对数据结构的理解,提高了综合运用课程知识的能力,培养了独立思考、深入研究、分析问题和解决问题的能力。

    同时,我也明白了将理论知识与实际相结合的重要性,只有理论知识远远不够,因为在实际设计中还是会遇到不少问题,这次实验使我发现了自己很多知识漏洞,这对我今后的学习来说是一次非常宝贵的体验。

收获:

1)对平衡二叉树的构造、插入和删除的算法思想有了更清楚的认识,能够对平衡二叉树进行创建、调平、插入、删除等操作,实现动态的输入数据,实时的输出该树结构.

2)对多个程序的调用

八、附录

源代码:

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

#define LH +1
#define EH 0
#define RH -1
#define NULL 0

typedef struct BSTNode {
	int data;
	int bf;
	struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;

void CreatBST(BSTree &T);
void R_Rotate (BSTree &p);
void L_Rotate(BSTree &p);
void LeftBalance(BSTree &T);
void RightBalance(BSTree &T);
bool InsertAVL(BSTree &T,int e,bool &taller);
bool SearchBST(BSTree &T,int key);
void LeftBalance_div(BSTree &p,int &shorter);
void RightBalance_div(BSTree &p,int &shorter);
void Delete(BSTree q,BSTree  &r,int &shorter);
int DeleteAVL(BSTree &p,int x,int &shorter);
void PrintBST(BSTree T,int depth);

void main()
{
	BSTree T;
	int sear,cmd,depth;
	char ch;
	int shorter=0;
    bool taller=false;
	T=(BSTree)malloc(sizeof(BSTNode));
	T=NULL;
	printf("****************平衡二叉树的操作菜单****************\n");
	printf("                    1--创建\n");
	printf("                    2--查找\n");
    printf("                    3--插入\n");
   	printf("                    4--删除\n");
    printf("                    5--退出\n");
	printf("****************************************************\n");
	do
	{
        printf("\n请选择操作的编号:");
		scanf("%d",&cmd);
		getchar();
		switch(cmd)
		{
		case 1:
			CreatBST(T);break;
		case 2:
			printf("请输入您要查找的关键字:");
				scanf("%d",&sear);getchar();
			if(SearchBST(T,sear)) printf("关键字%d存在,查找成功!\n",sear);
			else printf("查找失败!\n");
			break;
		case 3:
			printf("请输入您要插入的关键字:");
				scanf("%d",&sear);getchar;
			InsertAVL(T,sear,taller);depth=0;
			PrintBST(T,depth);
			break;
		case 4:
			depth=0;
			printf("请输入你要删除的关键字: ");
			scanf("%d",&sear); getchar();
			DeleteAVL(T,sear,shorter);
			PrintBST(T,depth); 
			break;
		case 5:
			printf("结束!\n");
			break;
		default:
			printf("输入错误!\n");
		}
		if(cmd==5)
			break;
		printf("\n继续吗? y/n: ");
		scanf("%s",&ch);
		getchar();
		printf("\n");
	}while(ch=='y');
	printf("\n");
}

void CreatBST(BSTree &T)
{
	int depth;
	int e;
    bool taller=false;
	T = NULL;
	printf("\n请输入关键字(以-123结束建立平衡二叉树):");
	scanf("%d",&e);
	getchar();
	while(e != -123)
	{
		InsertAVL(T,e,taller);
		printf("\n请输入关键字(以-123结束建立平衡二叉树):");
		scanf("%d",&e);
		getchar();
		taller=false;
	}
	depth=0;
	printf("\n****************************************************\n");
	printf("                 您创建的二叉树为\n");
	if(T)
		PrintBST(T,depth);
	else
		printf("这是一棵空树!\n");
}

void R_Rotate (BSTree &p)    //对以*p为根的二叉排序树作右旋处理
{
	BSTree lc;
	lc=p->lchild;
	p->lchild=lc->rchild;
	lc->rchild=p;
	p=lc;
}

void L_Rotate(BSTree &p)   //对以*p为根的二叉排序树作左旋处理
{
	BSTree rc;
	rc=p->rchild;
	p->rchild=rc->lchild;
	rc->lchild=p;
	p=rc;
}

void LeftBalance(BSTree &T)    //对以指针T所指结点为根的二叉树作左平衡旋转处理
{
	BSTree lc,rd;
	lc=T->lchild;
	switch(lc->bf)
	{
	case LH:
		T->bf=lc->bf=EH;
		R_Rotate(T);
		break;
	case RH:
		rd=lc->rchild;
		switch(rd->bf)
		{
		case LH:
			T->bf=RH;lc->bf=EH;break;
		case EH:
			T->bf=lc->bf=EH;break;
		case RH:T->bf=EH;lc->bf=LH;break;
		}
		rd->bf=EH;
		L_Rotate(T->lchild);
		R_Rotate(T);
	}
}

void RightBalance(BSTree &T)     //对以指针T所指结点为根的二叉树作右平衡旋转处理
{
	BSTree rc,ld;
	rc=T->rchild;
	switch(rc->bf)
	{
	case RH:
		T->bf=rc->bf=EH;
		L_Rotate(T);
		break;
	case LH:
		ld=rc->lchild;
		switch(ld->bf)
		{
		case RH:T->bf=LH;rc->bf=EH;break;
		case EH:T->bf=rc->bf=EH;break;
		case LH:T->bf=EH;rc->bf=RH;break;
		}
		ld->bf=EH;
		R_Rotate(T->rchild);
		L_Rotate(T);
	}
}

bool InsertAVL(BSTree &T,int e,bool &taller)  //插入结点e
{
	if(!T)
	{
		T=(BSTree)malloc(sizeof(BSTNode));
		T->data=e;
		T->lchild=T->rchild=NULL;
		T->bf=EH;
		taller=true;
	}
	else{
		if(e==T->data)
		{
			taller=false;
			printf("已存在相同关键字的结点!\n");
			return 0;
		}
		if(e<T->data)
		{
			if(!InsertAVL(T->lchild,e,taller))
				return 0;
			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 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;
			}
		}
	}
}

bool SearchBST(BSTree &T,int key)   //查找元素key是否在树T中
{
	if(!T)
		return false;
	else if(key==T->data)
		return true;
	else if(key<T->data)
		return SearchBST(T->lchild,key);
	else
		return SearchBST(T->rchild,key);
}

void LeftBalance_div(BSTree &p,int &shorter)     //删除结点时左平衡旋转处理
{
	BSTree  p1,p2;
	if(p->bf==1) 
	{ p->bf=0; shorter=1; }
	else if(p->bf==0)
	{ p->bf=-1; shorter=0; }
	else  
	{
		p1=p->rchild;
		if(p1->bf==0)
		{
			L_Rotate(p);
			p1->bf=1; p->bf=-1; shorter=0;
        }
		else if(p1->bf==-1)
        {
			L_Rotate(p);
            p1->bf=p->bf=0; shorter=1;
        }
		else 
        {
			p2=p1->lchild;
			p1->lchild=p2->rchild; p2->rchild=p1; p->rchild=p2->lchild; p2->lchild=p;
			if(p2->bf==0)
			{ p->bf=0; p1->bf=0; }
			else if(p2->bf==-1)
			{ p->bf=1;p1->bf=0; }
			else 
			{ p->bf=0;p1->bf=-1; }
            p2->bf=0; p=p2; shorter=1;
		}
  }

}

void RightBalance_div(BSTree &p,int &shorter)    //删除结点时右平衡旋转处理
{
	BSTree  p1,p2;
	if(p->bf==-1)
	{ p->bf=0; shorter=1; }
    else if(p->bf==0)
	{ p->bf=1; shorter=0; }
    else
    { 
		p1=p->lchild;
        if(p1->bf==0)
        {
			R_Rotate(p);
            p1->bf=-1; p->bf=1; shorter=0;
		}
        else if(p1->bf==1)
        {
			R_Rotate(p);
            p1->bf=p->bf=0; shorter=1;
        }
        else
        {
            p2=p1->rchild;
            p1->rchild=p2->lchild; p2->lchild=p1; p->lchild=p2->rchild; p2->rchild=p;
            if(p2->bf==0)
            { p->bf=0; p1->bf=0; }
            else if(p2->bf==1)
            { p->bf=-1; p1->bf=0; }
            else 
            { p->bf=0; p1->bf=1; }
            p2->bf=0; p=p2; shorter=1;
		}
	}
}

void Delete(BSTree q,BSTree  &r,int &shorter)         //删除结点
{
	if(r->rchild==NULL)
    {
		q->data=r->data; q=r;
        r=r->lchild; free(q);
        shorter=1;
	}
    else 
    { 
		Delete(q,r->rchild,shorter);
        if(shorter==1) 
			RightBalance_div(r,shorter);
	}
}

int DeleteAVL(BSTree &p,int x,int &shorter)      //平衡二叉树的删除操作
{
	int k;
    BSTree q;
    if(p==NULL)  { printf("不存在要删除的关键字!\n"); return 0;}
    else if(x<p->data)
    { 
		k=DeleteAVL(p->lchild,x,shorter);
        if(shorter==1)
			LeftBalance_div(p,shorter);
		return k;
	}
	else if(x>p->data)
    {
		k=DeleteAVL(p->rchild,x,shorter);
		if(shorter==1)
			RightBalance_div(p,shorter);
		return k;
	}
	else
	{
		q=p;
		if(p->rchild==NULL) 
		{ p=p->lchild; free(q); shorter=1; }
        else if(p->lchild==NULL)
		{ p=p->rchild; free(q); shorter=1; }
        else
        {
			Delete(q,q->lchild,shorter);
			if(shorter==1)
				LeftBalance_div(p,shorter);
			p=q; 
		}
       return 1;
	}
}

void PrintBST(BSTree T,int depth)
{
	int i;
		if(T->rchild)
			PrintBST(T->rchild,depth+1);
		for(i=1;i<=depth;i++)
			printf("     ");
		printf("%d\n",T->data);
		if(T->lchild)
			PrintBST(T->lchild,depth+1);
}

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