数据结构课设(五)二叉排序树与平衡二叉树的实现

数据结构课设(五)二叉排序树与平衡二叉树的实现 C代码


一、问题描述

假定二叉排序树与平题所处理数据均为整型。分别采用二叉链表和顺序表作存储结构,实现对二叉衡二叉树的操作。具体要求如下:
(1)用二叉链表作存储结构:
①读入一个整数序列L(要求该整数序列从磁盘文件读取),生成一棵二叉排序树②对二叉排序树T作中序遍历,输出结果。③计算二叉排序树T查找成功的平均查找长度,输出结果。④输入元素x,查找二叉排序树T。若存在含x的结点,则删除该结点,并作中序遍历(执行操作②);否则输出信息“无x”。⑤用数列L,生成一棵平衡的二叉排序树BT。如果当插人新元素之后,发现当前的二叉排序树BT不是平衡的二叉排序树,则将它转换成平衡的二叉排序树BT.⑥计算平衡的二叉排序树BT的平均查找长度,输出结果。
(2)用顺序表作存储结构:
①读人一个整数序列L(要求该整数序列从磁盘文件读取),生成一棵二叉排序树T.②对二叉排序树T作中序遍历,输出结果。③计算二叉排序树T查找成功的平均查找长度,输出结果。④输人元素x,查找二叉排序树T. 若存在含x的结点,则删除该结点,并作中序遍历。

二、代码

经过分析,本题需要完成的需求是:分别以顺序表和二叉链表完成输入,中序遍历排序,查删结点,求平均查找长度的操作。

1.C代码

代码如下(示例):

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

typedef struct Node
{
	int data;
	int height;
	Node *rchild,*lchild,*parent;
}BSTNode,*BSTree;

BSTNode *T;

void insertBST(int k)
{
	BSTNode *y=NULL;
	BSTNode *x=T;
	BSTNode *z;
	z=(BSTNode *)malloc(sizeof(Node));
	z->data=k;
	z->height=1;
	z->lchild=NULL;
	z->rchild=NULL;
	while(x!=NULL)
	{
		y=x;
		if(z->data<x->data)
		{
			x=x->lchild;
			z->height++;
		}
		else
		{
			x=x->rchild;
			z->height++;
		}
	}
	z->parent=y;
	if(y==NULL) T=z;
	else
	{
	if(z->data<y->data) y->lchild=z;
	else y->rchild=z;
	}
	}

void Inorder(BSTNode *u)
{
	if(u==NULL) return;
	Inorder(u->lchild);
	printf("%d ",u->data);
	Inorder(u->rchild);
}
double CalLength(BSTree *T)
{
	static double length=0;
	static int n=0;
	if(*T)
	{
		length+=(*T)->height;
		CalLength(&(*T)->lchild);
		n++;
		CalLength(&(*T)->rchild);
	}
	return length/n;
}
BSTree SearchDeleteBST(int  key)  //删除函数
{
	BSTree p=T,q=NULL,s,f;
    while(p!=NULL)   //查找要删除的点
    {
        if(p->data==key)
		break;
        q=p; //q指向要删结点的父母
        if(p->data>key)   p=p->lchild;
        else p=p->rchild;
    }
    if(p==NULL)
	return  T;    //查找失败
    if(p->lchild==NULL)     //p指向当前要删除的结点
    {
        if(q==NULL)   T=p->rchild;  
        else if(q->lchild==p)    q->lchild=p->rchild;  //p为q的左孩子
        else q->rchild=p->rchild; //p为q的右孩子
        free(p);
    }
	else
	{           //p的左孩子不为空
        f=p;
        s=p->lchild;
        while(s->rchild)   //左拐后向右走到底
        {
            f=s;
            s=s->rchild;
        }
        if(f==p)    f->lchild=s->lchild;  //重接f的左子树
        else    f->rchild=s->lchild;   //重接f的右子树
        p->data=s->data;
        free (s);
    }
    return  T;
}
int searchBST(BSTree T,int key,BSTree f,BSTree *p) //查找函数
{
    if(!T)
	{
		*p=f;
		return 0;
	}           //查找不成功
	else if(key==T->data)    
	{
		*p=T;
		return 1;
	} /*查找成功*/
	else if(key<T->data)   searchBST(T->lchild,key,T,p);   //在左子树中继续查找
	else  searchBST(T->rchild,key,T,p); //在右子树中继续查找
}
int main()
{
    int num;
    char ch;
    BSTree p=NULL;
	printf("输入L:");
    do
	{	
        scanf("%d",&num);
        insertBST(num);
        scanf("%c",&ch);
        if(ch=='\n') break;
    }while(ch!='\n');
    printf("中序遍历结果为:\n");
    Inorder(T); 
    printf("\n");
    printf("平均查找长度为:%3.1f",CalLength(&T));
    printf("\n");
    printf("输入查找元素,若该结点存在则删除该结点:");
    scanf("%d",&num); 
    if(searchBST(T,num,NULL,&p))
    {
        T=SearchDeleteBST(num);
        printf("\n删除成功,中序遍历输出:\n");
        Inorder(T);
    }
    else
        printf("没有找到该结点%d",num);
    return 0;
}
#include<stdio.h>
#include<stdlib.h>
#define LH 1
#define EH 0
#define RH -1
typedef struct Node
{
	int data;
	int BF;//平衡因子(balance factor)
	struct Node *lchild,*rchild;
}BSTNode,*BSTree;
void R_Rotate(BSTree *p)//以p为根节点的二叉排序树进行右旋转
{
	BSTree L;
	L=(*p)->lchild;
	(*p)->lchild=L->rchild;
	L->rchild=(*p);
	*p=L;//p指向新的根节点
}
void L_Rotate(BSTree *p)//以p为根节点的二叉排序树进行左旋转
{
	BSTree R;
	R=(*p)->rchild;
	(*p)->rchild=R->lchild;
	R->lchild=(*p);
	*p=R;
}
void LeftBalance(BSTree *T)
{
	BSTree L,Lr;
	L=(*T)->lchild;
	switch(L->BF)
	{
	  //检查T的左子树平衡度,并作相应的平衡处理
		case LH://新节点插入在T的左孩子的左子树上,做单右旋处理
		(*T)->BF=L->BF=EH;
		R_Rotate(T);
		break;
		case RH://新插入节点在T的左孩子的右子树上,做双旋处理
		Lr=L->rchild;
		switch(Lr->BF)
	    {
		    case LH:
		    (*T)->BF=RH;
		    L->BF=EH;
		    break;
		    case EH:
		    (*T)->BF=L->BF=EH;
		    break;
		    case RH:
		    (*T)->BF=EH;
		    L->BF=LH;
		    break;
	    }
		Lr->BF=EH;
	    L_Rotate(&(*T)->lchild);
	    R_Rotate(T);
	}
}
void RightBalance(BSTree *T)
{ 
	BSTree R,Rl;
	R=(*T)->rchild;
	switch(R->BF)
	{
	case RH://新节点插在T的右孩子的右子树上,要做单左旋处理
	        (*T)->BF=R->BF=EH;
	     L_Rotate(T);
	     break;
	case LH://新节点插在T的右孩子的左子树上,要做双旋处理
	    Rl=R->lchild;
	    switch(Rl->BF)
	    {
		    case LH:
		    (*T)->BF=EH;
		    R->BF=RH;
		    break;
		    case EH:
		    (*T)->BF=R->BF=EH;
		    break;
		    case RH:
		    (*T)->BF=LH;
		    R->BF=EH;
		    break;
	    }
	Rl->BF=EH;
	R_Rotate(&(*T)->rchild);
	L_Rotate(T);
 }
}

bool InsertAVL(BSTree *T,int e,bool *taller)//变量taller反应T长高与否
{
	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;
			return false; 
		}
		if(e<(*T)->data)
		{
			if(!InsertAVL(&(*T)->lchild,e,taller))//未插入
			  return false;
			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
		{
			//应在T的右子树中搜寻
			if(!InsertAVL(&(*T)->rchild,e,taller))
			    return false;
			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 true;
}

bool Find(BSTree T,int key)
{
	if(!T)
	return false;
	else if(T->data==key)
	return true;
	else if(T->data<key)
	return Find(T->rchild,key);
	else
	return Find(T->lchild,key);
}
void Inorder(BSTree T)
{
	if(T)
	{
		printf("%d",T->data);
		if(T->lchild||T->rchild)
		{
			printf("(");
			Inorder(T->lchild);
			printf(",");
			Inorder(T->rchild);
			printf(")");
		}
	}
}
double CalAveLength(BSTree T,int A[],int num)
{
	double len=0;
	int i;
	BSTree rt;
	
	for(i=0;i<num;i++)
	{
		rt=T;
		for(;;)
		{
			len++;
			if (rt->data==A[i]) break;
			if(rt->data<A[i])
			rt=rt->rchild;
			else
			rt=rt->lchild;
		}
	}
	return (double)len/num;
}
int main()
{
	int i;
	int j;//插入数 
	int num;
	int A[]={3,2,1,4,5,6,7,10,9,8};
	BSTree T=NULL;
	bool taller;
	num=sizeof(A)/sizeof(int);
	for(i=0;i<sizeof(A)/sizeof(int);i++)
	InsertAVL(&T,A[i],&taller);
	Inorder(T);
	printf("\n");
	printf("插入结点值:");
	scanf("%d",&j);
	InsertAVL(&T,j,&taller);
	Inorder(T);
	printf("\n");
	printf("平均查找长度为:%3.1f",CalAveLength(T,A,num));
	return 0;

}

#include<stdio.h>
#include<stdlib.h>
#define N 100
typedef struct
{
	int *data;
	int dnum;
}BST;
float length;
void InsertBST(BST T,int i,int key)
{
	if(i<1||i>N) 
	printf("ERROR!\n");
	if(T.data[i]==0) 
	T.data[i]=key;
	else if(key<T.data[i]) 
	InsertBST(T,2*i,key);
	else InsertBST(T,2*i+1,key);
}

BST CreatBST(int *A,int num)
{
	BST T;
	int i,j;
	T.data=(int *)malloc(N*sizeof(int));
	for(j=0;j<N;j++)
	T.data[j]=0;
	T.dnum=0;
	for(i=0;i<num;i++)
	{
		InsertBST(T,1,A[i]);
		++T.dnum;
	}
	return T;
}

void Inorder(BST T,int i)
{
	if(T.data[i])
	{
		Inorder(T,2*i);
		printf("%d ",T.data[i]);
		Inorder(T,2*i+1);
	}
}

int search(BST T,int key,int i)
{
	length++;
	if(!T.data[i]) return 0;
	else if(key==T.data[i]) return i;
	else if(key<T.data[i]) search(T,key,2*i);
	else search(T,key,2*i+1);
}
BST DeleteBST(BST T,int key)
{
	BST q;
	int i;
	q.data=(int *)malloc(N*sizeof(int));
	for(i=0;i<N;i++) 
	q.data[i]=0;
	q.dnum=0;
	for(i=1;i<N&&T.dnum>0;i++)
	{
		if(T.data[i]==0||T.data[i]==key) continue;   
		InsertBST(q,1,T.data[i]);   
		--T.dnum;   
		++q.dnum;
	}
	delete T.data;
	return q;
}
int main()
{
	BST T;
	int A[N];
	char ch;
	int i=0;
	int num,j;
	printf("输入L:");
	do
	{
		scanf("%d",&num);
		A[i++]=num;
	    scanf("%c",&ch);
	    if(ch=='\n') break;
	}while(ch!='\n');
	
	T=CreatBST(A,i);
	printf("中序遍历结果:");
	Inorder(T,1);
	printf("\n");
	length=0;
	
	for(int s=0;s<T.dnum;s++)
	search(T,A[s],1);
	
	printf("平均查找长度:");
	
	float f;
	f=length/T.dnum;
	printf("%3.1f\n",f);
	printf("输入查找元素,若该节点存在,则删除该结点:");
	scanf("%d",&num);
	j=search(T,num,1);
	if(j)
	{
		T=DeleteBST(T,num);
		printf("删除成功,中序遍历结果:");
		Inorder(T,1);
		i--;
	} 
	else printf("没有找到该结点%d",num);
}


总结

构造二叉排序树。我们对于给定序列,取其第一个点为根结点,然后依次选择后续节点边比较边插入。如果比当前结点小,往该节点左子树移动比较,如果比当前结点大,则往该节点右子树移动比较。直到到一个待比较位置为空的位置,就是该节点的最终位置。
查找操作通过递归算法实现。思路很简单,仅需要从根节点开始比较就可以,比当前结点大就找左子树,小就找右子树直到找到为止。
删除操作相对于前面的查找与插入就复杂一些了。删除某元素需要维护二叉排序树的形状。

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值