1、用二叉链表作存储结构实现二叉排序树。
2、用顺序表(一维数组)作存储结构----静态链表
3、用二叉链表作存储结构实平衡的二叉排序树。
五、反思启发
在编写代码的过程中,我经常分不清楚BSTNode 和BSTree以及是否要带*,导致及时明白算法过程,但编写过程出现了巨大的问题。在建立树的函数就有很多的表达方式,我需要考虑这个函数对后面函数的影响。同时,在编写删除结点的函数和计算平均查找长度的函数也花费了不少的时间,在这一过程中,我对链表和指针的应用能力得到了极大的提升。
六、代码附录
1、用二叉链表作存储结构实现二叉排序树。
#include
#include
#include
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=x->lchild;
z->height++;
}
else
{
x=x->rchild;
z->height++;
}
}
z->parent=y;
if(y==NULL) T=z;
else
{
if(z->data
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
else searchBST(T->rchild,key,T,p); //在右子树中继续查找
}
int main()
{
int num;
char ch;
BSTree p=NULL;
printf("输入一串数,每个数以空格分开:");
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;
}
2、用顺序表(一维数组)作存储结构----静态链表
#include
#include
#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
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
T.dnum=0;
for(i=0;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
}
BST DeleteBST(BST T,int key)
{
BST q;
int i;
q.data=(int *)malloc(N*sizeof(int));
for(i=0;i
q.dnum=0;
for(i=1;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("请输入数据:");
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
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);
}
3、用二叉链表作存储结构实平衡的二叉排序树。
#include
#include
#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
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
rt=T;
for(;;)
{
len++;
if (rt->data==A[i]) break;
if(rt->data 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
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;
}