功能要求:
//(1)生成一组随机数并输出。
//(2)利用生成的随机数来建立平衡二叉排序树,并显示。
//(3)分别计算成功和失败的平均查找长度。
//(4)按数值递减次序输出数据。
//(5)功能:检索(输出依次比较的数据)、插入、删除。
不多说,上代码!
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
#include<math.h>
int *ptr=NULL,temp;//中序遍历返回建立数组
int *ptr1=NULL,temp1;
typedef int Elementtype;
typedef struct Avltree
{
Elementtype key; //关键字大小
struct Avltree* lchild, * rchild, * parent; //左右孩子结点和父结点
}avlnode;
void Operation_AVL(avlnode*&node,avlnode*b); //不平衡后调整的主要方式
avlnode* Insertnode(avlnode*& node,Elementtype k); //插入结点,返回该结点
avlnode* Creat_AVL(int*p,int n); //建立AVL树,返回AVL的根结点
void Parent_adjust(avlnode*& bt); //结点父结点指向
int Get_height(avlnode* node); //获取当前结点的深度
//操作
void AVL_ASLsucc(avlnode*node,int m,int &succ); //查找成功的平均查找长度
void AVL_ASLunsucc(avlnode *node,int t,int &unsucc); //查找失败的平均查找长度
void Decrease_sort(avlnode *node,int n,int flag); //递减输出二叉树的数据
void Search_element(avlnode *node,Elementtype e); //在二叉树中查找值为e的某元素
void Insert_element(avlnode *&node,Elementtype e); //插入某值为e的结点
void Creat_order(avlnode *node,int n,int flag); //中序遍历结果
avlnode *Inorder(avlnode *node,Elementtype e,int n); //找到某结点中序遍历的前驱结点,是删除操作的一个工具
avlnode *Search(avlnode*node,Elementtype e); //返回前驱结点,是删除操作的一个工具
void Delete_element(avlnode*&snode,avlnode *node,Elementtype e,int n);//删除某值为e的结点
void Print_AVL(avlnode* bt); //打印AVL
int main()
{
srand((int)time(0)); //种子
Elementtype e1,e2,e3; //查找,插入和删除
int n; //随机数的个数
int *p=NULL; //存放随机数
char sign; //输入的代号
avlnode* bt=NULL,*pt=NULL; //储存根结点
int i, j;
int succ=0,unsucc=0; //成功和失败的查找长度
int m=1,t=1; //结点深度
int flag=0;
printf("请输入建立平衡二叉树所需要的数据个数:");scanf("%d", &n);
p = (int* )malloc(n * sizeof(int));
if (p)
{
for (i = 0; i < n; i++)
{
j = 0; *(p + i) = rand() % 100;
while (j < i && (*(p + j) != *(p + i) ) )
j++;
if (j != i)//有重复就重新对这个元素赋值
i -= 1;
}
printf("这一组随机数是:");
for (i = 0; i < n; i++)
printf("%d ", *(p + i));
printf("\n");
}
printf("建立的二叉树的括号表示法为:");
bt= Creat_AVL(p,n);//建立二叉树,返回根结点
Print_AVL(bt);//打印二叉树
Creat_order(bt,n,flag);
printf("\n\n");
while(1)
{
setbuf(stdin, NULL);//清除输入缓冲区
printf(" ******************平衡二叉树操作表*********************\n");
printf(" ***********《请输入功能的代号来实现相应功能》**************\n");
printf(" A:计算平衡二叉树成功查找的平均查找长度\n");
printf(" B:计算平衡二叉树失败查找的平均查找长度\n");
printf(" C:按数值递减次序输出平衡二叉树中的数据\n");
printf(" D:查找某个值,若树中存在该值,依次输出所比较数据\n");
printf(" E:插入一个数据至平衡二叉树中\n");
printf(" F:删除平衡二叉树中某个结点\n");
printf(" G:退出\n");
printf("请输入你的选择->");
scanf("%c",&sign);
if(sign=='A'||sign=='B'||sign=='C'||sign=='D'||sign=='E'||sign=='F')
switch(sign)
{
case 'A':
AVL_ASLsucc(bt,m,succ);
if(bt==NULL)
printf("查找成功的平均查找长度是:%d\n",succ);
else
printf("查找成功的平均查找长度是:%d/%d\n",succ+1,n);
succ=0;
break;
case 'B':
AVL_ASLunsucc(bt,t,unsucc);
if(bt==NULL)
printf("查找失败的平均查找长度是:%d\n",unsucc);
else
printf("查找失败的平均查找长度是:%d/%d\n",unsucc,n+1);
unsucc=0;
break;
case 'C':
printf("递减输出二叉树的数据:");
if(ptr!=NULL)
free(ptr);
Decrease_sort(bt,n,flag);
for(int i=0;i<n;i++)
printf("%4d",*(ptr+i));
printf("\n");
break;
case 'D':
printf("请输入需要查找的数据->");scanf("%d",&e1);
setbuf(stdin, NULL);
printf("在二叉树中查找元素依次比较的数据是:");
Search_element(bt,e1);
break;
case 'E':
printf("请输入所要插入的数据->");scanf("%d",&e2);
setbuf(stdin, NULL);
Insert_element(bt,e2);
printf("插入值为%d的结点后,二叉树的括号表示法为:",e2);
Print_AVL(bt);
printf("\n");
n+=1;
if(ptr1!=NULL)
free(ptr1);
Creat_order(bt,n,flag);
break;
case 'F':
printf("请输入所要删除的数据->");scanf("%d",&e3);
setbuf(stdin, NULL);
Delete_element(bt,bt,e3,n);
if(bt==NULL)
printf("删除操作后,二叉树为空");
else
{
printf("删除操作后,二叉树的括号表示法为:");
Print_AVL(bt);
}
printf("\n");
n-=1;
if(ptr1!=NULL)
free(ptr1);
Creat_order(bt,n,flag);
break;
default:break;
}
else if(sign=='G')
{
printf("******欢迎下次使用******");
setbuf(stdin, NULL);
break;
}
else
{
printf("输入错误!请重新输入\n");
setbuf(stdin, NULL);
}
}
return 0;
}
void Creat_order(avlnode*node,int n,int flag)
{
if(flag==0)
{
temp1=n-1;
ptr1=(int *)malloc(sizeof(int)*n);
flag++;
}
if(node!=NULL)
{
Creat_order(node->lchild,n,flag);
*(ptr1+temp1)=node->key;
temp1--;
Creat_order(node->rchild,n,flag);
}
}
avlnode* Insertnode(avlnode*& node, Elementtype k)//插入
{
if (node == NULL)
{
node = (avlnode*)malloc(sizeof(avlnode));
if (node)
{
node->key = k;
node->lchild = NULL; node->rchild = NULL;
node->parent = NULL;
}
return node;
}
else if (k < node->key)//小于根结点的值
{
return Insertnode(node->lchild, k);
}
else//大于根结点的值
{
return Insertnode(node->rchild, k);
}
}
void Parent_adjust(avlnode*& bt)//建立父结点指向,递归
{
avlnode* p1,*p2;
if (bt == NULL)//根结点指向NULL
return;
p1 = bt->lchild; p2 = bt->rchild;
if (p1 != NULL && p2 != NULL)
{
p1->parent = bt;
p2->parent = bt;
Parent_adjust(p1);
Parent_adjust(p2);
}
else if (p1 != NULL && p2 == NULL)
{
p1->parent = bt;
Parent_adjust(p1);
}
else if (p1 == NULL && p2 != NULL)
{
p2->parent = bt;
Parent_adjust(p2);
}
else
return;
}
int Get_height(avlnode* node)//返回左右子树的高度差
{
if (node == NULL)
return 0;
else if (node->lchild == NULL && node->rchild == NULL)
return 1;
else
return Get_height(node->lchild) > Get_height(node->rchild) ? (Get_height(node->lchild) + 1) : (Get_height(node->rchild) + 1);
}
avlnode* Creat_AVL(int *p, int n)//建立平衡二叉树
{
avlnode* bt=NULL,*b=NULL;
for (int i = 0; i < n; i++)
{
b=Insertnode(bt,*(p+i));//插入结点,返回该结点
Parent_adjust(bt); //建立父结点指向
Operation_AVL(bt,b); //调整平衡二叉树
}
return bt;
}
void AVL_ASLsucc(avlnode*node,int m,int &succ)
{
if(node==NULL)
return;
else if(node->lchild!=NULL && node -> rchild!=NULL)//都不空
{
m++;
succ+=2*m;
AVL_ASLsucc(node->lchild,m,succ);
AVL_ASLsucc(node->rchild,m,succ);
}
//其中一个为空
else if(node->lchild==NULL&&node->rchild!=NULL || node->lchild!=NULL && node->rchild==NULL)
{
m++;
succ+=m;
if(node->lchild==NULL)
AVL_ASLsucc(node->rchild,m,succ);
else
AVL_ASLsucc(node->lchild,m,succ);
}
//都为空
else return;
}
void AVL_ASLunsucc(avlnode*node,int t,int &unsucc)
{
if(node==NULL)
return;
else if(node->lchild==NULL&&node->rchild==NULL)//都空
{
unsucc+=2*t;
return;
}
//其中一个为空
else if(node->lchild==NULL&&node->rchild!=NULL || node->lchild!=NULL&&node->rchild==NULL)
{
unsucc+=t;
if(node->lchild==NULL)
{
t++;
AVL_ASLunsucc(node->rchild,t,unsucc);
}
else
{
t++;
AVL_ASLunsucc(node->lchild,t,unsucc);
}
}
//都不空
else
{
t++;
AVL_ASLunsucc(node->lchild,t,unsucc);
AVL_ASLunsucc(node->rchild,t,unsucc);
}
}
void Decrease_sort(avlnode*node,int n,int flag)
{
if(flag==0)
{
temp=n-1;
ptr=(int *)malloc(sizeof(int)*n);
flag++;
}
if(node!=NULL)
{
Decrease_sort(node->lchild,n,flag);
*(ptr+temp)=node->key;
temp--;
Decrease_sort(node->rchild,n,flag);
}
}
void Search_element(avlnode*node,Elementtype e)//查找元素e
{
if(node==NULL)
{
printf("\n查找失败!二叉树中不含有元素%d\n",e);
return;
}
if(e<node->key)
{
printf("%d ",node->key);
Search_element(node->lchild,e);
}
else if(e>node->key)
{
printf("%d ",node->key);
Search_element(node->rchild,e);
}
else
{
printf("%d \n",node->key);
printf("查找成功!二叉树中含有元素%d\n",e);
return;
}
}
void Insert_element(avlnode *&node,Elementtype e)//插入结点
{
avlnode* b=NULL;
b=Insertnode(node,e);//插入结点,返回该结点
Parent_adjust(node);//建立父结点指向
Operation_AVL(node,b);
}
void Delete_element(avlnode*&snode,avlnode*node,Elementtype e,int n)//删除某个结点
{
if(node==NULL)
{
//没找到该元素直接返回,查找失败
printf("二叉树中不含有需要删除的元素%d\n",e);
return;
}
if(e<node->key)
Delete_element(snode,node->lchild,e,n);
else if(e>node->key)
Delete_element(snode,node->rchild,e,n);
//找到元素值为e的结点node
else
{
avlnode* b=NULL;
//结点是叶子结点
if(node->lchild==NULL && node->rchild==NULL)
{
b=node->parent;
if(b==NULL)//删除的是根结点
snode=NULL;
else//删除的不是根结点
{
//清除孩子结点和父结点指向
if(node->parent->lchild==node)
node->parent->lchild=NULL;
else if(node->parent->rchild==node)
node->parent->rchild=NULL;
node->parent=NULL;
Operation_AVL(snode,b);//进行调整
}
}
//结点是单分支结点
else if(node->lchild==NULL&&node->rchild!=NULL || node->lchild!=NULL&&node->rchild==NULL)//结点是单分支结点
{
if(node->parent==NULL)//删除的是根结点
{
if(node->lchild!=NULL)//根结点的左孩子不空
{
snode=node->lchild;
node->lchild->parent=node->parent;
free(node);
}
else//根结点的右孩子不空
{
snode=node->rchild;
node->rchild->parent=node->parent;
free(node);
}
}
else//删除的不是根结点
{
//用单分支结点的左孩子结点或者是右孩子结点取缔要被删除的结点
if(node->lchild!=NULL)//左孩子不空
{
node->lchild->parent=node->parent;
if(node->parent->lchild==node)//左孩子是要删除的
node->parent->lchild=node->lchild;
else//右孩子是要删除的
node->parent->rchild=node->lchild;
b=node->lchild;//从替换的结点开始向根结点方向寻找不平衡的点
node->lchild=NULL;
node->parent=NULL;
free(node);
}
//用单分支结点的左孩子结点或者是右孩子结点取缔要被删除的结点
else if(node ->rchild!=NULL)//右孩子不空
{
node->rchild->parent=node->parent;
if(node->parent->lchild==node)//左孩子是要删除的
node->parent->lchild=node->rchild;
else//右孩子是要删除的
node->parent->rchild=node->rchild;
b=node->rchild;//从替换的结点开始向根结点方向寻找不平衡的点
node->rchild==NULL;
node->parent==NULL;
free(node);
}
//看是否平衡,不平衡就操作
Operation_AVL(snode,b);//进行调整
}
}
//结点是双分支结点
else
{
avlnode* tnode=NULL;//储存前驱结点
//找出中序遍历的前驱结点替换该结点
tnode=Inorder(snode,e,n); //中序遍历前驱结点,可能是叶子结点或者是单分支结点
if(node->parent==NULL)//删除的是根结点
{
snode=tnode; //根结点变化
tnode->rchild=node->rchild;//连接右边
if(node->rchild!=NULL)
node->rchild->parent=tnode;
b=snode;
if(node->lchild!=tnode) //前驱结点不是根结点的左孩子,左边连接需要进一步操作
{
//tnode可能存在左孩子
tnode->parent->rchild=tnode->lchild;
if(tnode->lchild!=NULL)
tnode->lchild->parent=tnode->parent;
tnode->lchild=node->lchild;//连接左边
node->lchild->parent=tnode;
}
tnode->parent=node->parent;
free(node);
Operation_AVL(snode,b);
}
else//删除的不是根结点
{
tnode->rchild=node->rchild;//连接右边
if(node->rchild!=NULL)
node->rchild->parent=tnode;
b=node;
if(node->lchild!=tnode)//前驱结点不是根结点的左孩子,左边连接需要进一步操作
{
tnode->parent->rchild=tnode->lchild;
if(tnode->lchild!=NULL)
tnode->lchild->parent=tnode->parent;
tnode->lchild=node->lchild;//连接左边
node->lchild->parent=tnode;
}
tnode->parent=node->parent;
if(node->parent->rchild==node)
tnode->parent->rchild=tnode;
else
tnode->parent->lchild=tnode;
Operation_AVL(snode,b);
}
}
}
}
avlnode *Search(avlnode*node,Elementtype e)
{
if(e<node->key)
{
Search(node->lchild,e);
}
else if(e>node->key)
{
Search(node->rchild,e);
}
//找到中序遍历的前驱结点
else
{
printf("%d",node->key);
return node;
}
}
avlnode *Inorder(avlnode *node,Elementtype e,int n)
{
int t=0;
//找到中序遍历前驱结点的key
for(int i=0;i<n;i++)
{
if(*(ptr1+i)==e)
{
t=*(ptr1+i+1);
break;
}
}
return Search(node,t);
}
void Operation_AVL(avlnode*& node,avlnode*b)
{
avlnode *s=NULL;
while (b != NULL && abs( Get_height(b->lchild) - Get_height(b->rchild) ) != 2)
b = b->parent;
if (b != NULL)//说明出现了不平衡,且b结点是离插入结点最近不平衡结点
{
if (b->parent==NULL)//根结点不平衡
{
if ((Get_height(b->lchild) - Get_height(b->rchild)) == 2)
{
if (( Get_height(b->lchild->lchild)-Get_height(b->lchild->rchild) )==1)//LL root
{
s = b->lchild; //s是失衡结点的左孩子
node=s; //根结点变为s,关键的一步!!!
s->parent = b->parent; //s的父结点等于失衡结点的父结点
b->lchild = s->rchild; //失衡结点的左孩子等于s的右孩子
if(s->rchild!=NULL)
s->rchild->parent=b; //s的右孩子结点的父结点等于失衡结点
s->rchild = b; //s的右结点等于失衡结点
b->parent = s; //失衡结点的父结点等于s
}
else if (( Get_height(b->lchild->lchild)-Get_height(b->lchild->rchild) )==-1)//LR root
{
s=b->lchild->rchild; //s等于刚插入的结点
node=s; //s作为根结点
s->parent->rchild=s->lchild;//s的父结点的右孩子等于s的左孩子
if(s->lchild!=NULL) //如果s的左孩子不空,s的左孩子的父结点等于s的父结点
s->lchild->parent=s->parent;
b->lchild=s->rchild; //b的左孩子等于s的右孩子
if(s->rchild!=NULL) //如果s的右孩子结点不空,那么s的右孩子的父结点等于b
s->rchild->parent=b;
s->lchild=s->parent; //s的左孩子等于s的父结点
s->parent->parent=s; //s的父结点的父结点等于s
s->parent=b->parent; //s->父结点等于b的父结点,该步骤往后面放,防止父结点提前为空
s->rchild=b; //s的右孩子结点等于b
b->parent=s; //b的父结点等于s
}
else//删除操作会出现的一种特殊情况,两种调整都行
{
s=b->lchild;
node=s;
s->parent=b->parent;
b->lchild=s->rchild;
if(s->rchild!=NULL)
s->rchild->parent=b;
s->rchild=b;
b->parent=s;
}
}
else if ((Get_height(b->lchild) - Get_height(b->rchild)) == -2)
{
if ( ( Get_height(b->rchild->lchild)-Get_height(b->rchild->rchild) )==1)//RL root
{
s = b->rchild->lchild;
node=s;
s->parent->lchild=s->rchild;
if(s->rchild!=NULL)
s->rchild->parent=s->parent;
b->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=b;
s->rchild=s->parent;
s->parent->parent=s;
s->parent=b->parent;
s->lchild=b;
b->parent=s;
}
else if ( ( Get_height(b->rchild->lchild)-Get_height(b->rchild->rchild) )==-1)//RR root
{
s=b->rchild; //s是失衡结点的右孩子
node=s; //根结点变为s
s->parent=b->parent; //s的父结点等于失衡结点的父结点
b->rchild=s->lchild; //失衡结点的右孩子等于s的左孩子
if(s->lchild!=NULL) //如果s的左孩子不空,s的左孩子的父结点等于失衡结点
s->lchild->parent=b;
s->lchild=b; //s的左孩子等于失衡结点
b->parent=s; //失衡结点的父结点等于s
}
else
{
s=b->rchild;
node=s;
s->parent=b->parent;
b->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=b;
s->lchild=b;
b->parent=s;
}
}
}
else//其它结点不平衡
{
if ((Get_height(b->lchild) - Get_height(b->rchild)) == 2)
{
if (( Get_height(b->lchild->lchild)-Get_height(b->lchild->rchild) )==1)//LL not root
{
s=b->lchild; //s等于失衡结点的左孩子
s->parent=b->parent; //s的父结点等于失衡结点的父结点
if(b->parent->lchild==b)
b->parent->lchild=s; //失衡结点的父结点的左孩子等于s
else
b->parent->rchild=s;
b->lchild=s->rchild; //失衡结点的左孩子等于s的右孩子
if(s->rchild!=NULL) //如果s的右孩子不空,那么s的右孩子的父结点等于失衡结点
s->rchild->parent=b;
s->rchild=b; //s的右孩子等于失衡结点
b->parent=s; //失衡结点的父结点等于s
}
else if (( Get_height(b->lchild->lchild)-Get_height(b->lchild->rchild) )==-1)//LR not root
{
s=b->lchild->rchild; //s等于刚插入的结点
s->parent->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=s->parent;
b->lchild=s->rchild;
if(s->rchild!=NULL)
s->rchild->parent=b;
s->lchild=s->parent; //s的左孩子等于s的父结点
s->parent->parent=s; //s的父结点的父结点等于s
s->parent=b->parent; //s->父结点等于b的父结点,该步骤往后面放,防止父结点提前为空
if(b->parent->rchild==b)
b->parent->rchild=s; //b结点的父节点的左孩子等于s
else
b->parent->lchild=s;
s->rchild=b; //s的右孩子结点等于b
b->parent=s; //b的父结点等于s
}
else
{
s=b->lchild; //s等于失衡结点的左孩子
s->parent=b->parent; //s的父结点等于失衡结点的父结点
if(b->parent->lchild==b)
b->parent->lchild=s; //失衡结点的父结点的左孩子等于s
else
b->parent->rchild=s;
b->lchild=s->rchild; //失衡结点的左孩子等于s的右孩子
if(s->rchild!=NULL) //如果s的右孩子不空,那么s的右孩子的父结点等于失衡结点
s->rchild->parent=b;
s->rchild=b; //s的右孩子等于失衡结点
b->parent=s; //失衡结点的父结点等于s
}
}
else if ((Get_height(b->lchild) - Get_height(b->rchild)) == -2)
{
if (( Get_height(b->rchild->lchild)-Get_height(b->rchild->rchild) )==1)//RL not root
{
s=b->rchild->lchild;
s->parent->lchild=s->rchild;
if(s->rchild!=NULL)
s->rchild->parent=s->parent;
b->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=b;
s->rchild=s->parent;
s->parent->parent=s;
s->parent=b->parent;
if(b->parent->rchild==b)
b->parent->rchild=s;
else
b->parent->lchild=s;
s->lchild=b;
b->parent=s;
}
else if (( Get_height(b->rchild->lchild)-Get_height(b->rchild->rchild) )==-1)//RR not root
{
s=b->rchild;
s->parent=b->parent;
if(b->parent->rchild==b)
b->parent->rchild=s;
else
b->parent->lchild=s;
b->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=b;
s->lchild=b;
b->parent=s;
}
else
{
s=b->rchild;
s->parent=b->parent;
if(b->parent->rchild==b)
b->parent->rchild=s;
else
b->parent->lchild=s;
b->rchild=s->lchild;
if(s->lchild!=NULL)
s->lchild->parent=b;
s->lchild=b;
b->parent=s;
}
}
}
}
}
void Print_AVL(avlnode* bt)//打印AVL树
{
if (bt != NULL)
{
printf("%d", bt->key);
if (bt->lchild != NULL || bt->rchild != NULL)
{
printf("(");
Print_AVL(bt->lchild);
if (bt->rchild != NULL)printf(",");
Print_AVL(bt->rchild);
printf(")");
}
}
}在这里插入代码片