数据结构课设(五)二叉排序树与平衡二叉树的实现 C代码
一、问题描述
假定二叉排序树与平题所处理数据均为整型。分别采用二叉链表和顺序表作存储结构,实现对二叉衡二叉树的操作。具体要求如下:
(1)用二叉链表作存储结构:
①读入一个整数序列L(要求该整数序列从磁盘文件读取),生成一棵二叉排序树②对二叉排序树T作中序遍历,输出结果。③计算二叉排序树T查找成功的平均查找长度,输出结果。④输入元素x,查找二叉排序树T。若存在含x的结点,则删除该结点,并作中序遍历(执行操作②);否则输出信息“无x”。⑤用数列L,生成一棵平衡的二叉排序树BT。如果当插人新元素之后,发现当前的二叉排序树BT不是平衡的二叉排序树,则将它转换成平衡的二叉排序树BT.⑥计算平衡的二叉排序树BT的平均查找长度,输出结果。
(2)用顺序表作存储结构:
①读人一个整数序列L(要求该整数序列从磁盘文件读取),生成一棵二叉排序树T.②对二叉排序树T作中序遍历,输出结果。③计算二叉排序树T查找成功的平均查找长度,输出结果。④输人元素x,查找二叉排序树T. 若存在含x的结点,则删除该结点,并作中序遍历。
二、代码
经过分析,本题需要完成的需求是:分别以顺序表和二叉链表完成输入,中序遍历排序,查删结点,求平均查找长度的操作。
1.C代码
代码如下(示例):文章来源:https://www.toymoban.com/news/detail-520814.html
#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);
}
总结
构造二叉排序树。我们对于给定序列,取其第一个点为根结点,然后依次选择后续节点边比较边插入。如果比当前结点小,往该节点左子树移动比较,如果比当前结点大,则往该节点右子树移动比较。直到到一个待比较位置为空的位置,就是该节点的最终位置。
查找操作通过递归算法实现。思路很简单,仅需要从根节点开始比较就可以,比当前结点大就找左子树,小就找右子树直到找到为止。
删除操作相对于前面的查找与插入就复杂一些了。删除某元素需要维护二叉排序树的形状。文章来源地址https://www.toymoban.com/news/detail-520814.html
到了这里,关于数据结构课设(五)二叉排序树与平衡二叉树的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!