题目:随机产生百万个整数,用该整数序列分别生成二叉排序树和AVL树。
(1)输出两棵树的结点总数;
(2)输出两棵树所有结点所在层次的总和;
(3)计算两棵树的平均查找长度ASL(查找成功时)。
注:rand()函数只能产生0~32767之间的整数,而二叉排序树中不允许有重复元素,因此实际上生成的树中结点不可能超过32768个。为能够生成百万个结点的树,生成的随机数必须超过0~32767的范围。
以十六进制来看,随机数范围在0000 ~ 7FFF之间,可以使用两个随机数的组合得到更大范围随机数:
n = (rand() << 15) | rand();
即第一个随机数左移15位 按位或 第二个随机数,从而范围可在0~231-1(1,073,741,823)之间。
知识点梳理:
1.AVL树的结构体定义:
由AVL树的定义,需要判断左右子树的高度差是否大于1,因此在树结点定义中增加Height域,在每次插入/删除结点时更新结点的Height域
struct AVLNode {
ElementType Data;
int Height;
struct AVLNode *Left;
struct AVLNode *Right;
};
2.求AVL树的高度:
int GetHeight(struct AVLNode*T){
if(T==NULL){
return 0;
}
else{
return 1+Max(GetHeight(T->Left),GetHeight(T->Right));
}
}
int Max(int a,int b){
Return a>b?a:b;
}
3.AVL树的左单旋:
struct AVLNode* SingleLeftRotation(struct AVLNode * K2) {//K2为不平衡点
struct AVLNode *K1;
K1 = K2->Left;旋转前K1和K2的关系
K2->Left = K1->Right;旋转后K1和K2的关系
K1->Right = K2;
// 旋转完后更新K1、K2的高度
K2->Height = Max(GetHeight(K2->Left), GetHeigth(K2->Right)) + 1;
K1->Height = Max(GetHeigth(K1->Left), K2->Height) + 1;
return K1;
}
4.AVL树的右单旋:
struct AVLNode * SingleRightRotation(struct AVLNode *K1) {
struct AVLNode *K2;
K2 = K1->Right;
K1->Right = K2->Left;
K2->Left = K1;
// 旋转完后更新K1、K2的深度
K1->Height = Max(GetHeight(K1->Left), GetHeight(K1->Right)) + 1;
K2->Height = Max(K1->Height, GetHeight(K2->Right)) + 1;
return K2;
}
5.AVL树的左双旋:
struct AVLNode * DoubleLeftRotation(struct AVLNode * K2)K2为不平衡结点
{
K2->Left = SingleRightRotation(K2->Left);
return SingleLeftRotation(K2);
}
5.AVL树的右双旋:
struct AVLNode * DoubleRightRotation(struct AVLNode * K1)
{
K1->Right = SingleLeftRotation(K1->Right);
return SingleRightRotation(K1);
}
6.AVL树的插入:
struct AVLNode * InsertAVL(struct AVLNode * T, ElementType X) {
if (T == NULL) {如果树为空,则创建一个新的结点为一棵树,将插入的数存入结点中
T = malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 1;插入数后设置树的高度为1
T->Left = T->Right = NULL;
} else if (X < T->Data) {树不为空时,若在插入的树小于根节点的内容
T->Left = InsertAVL(T->Left, X);在左子树中插入x
if (GetHeight(T->Left) - GetHeight(T->Right) == 2)判断在插入树后是否有结点不平衡
if (X < T->Left->Data)如果在左子树的外面进行插入
T = SingleLeftRotation(T);则进行左单旋转
else
T = DoubleLeftRotation(T);如果在左子树的里面插入,则进行双左旋
} else if (X > T->Data) {
T->Right = InsertAVL(T->Right, X);
if (GetHeight(T->Right) - GetHeight(T->Left) == 2)
if (X > T->Right->Data)
T = SingleRightRotation(T);
else
T = DoubleRightRotation(T);
}
// else X == T->Data的情况,不做任何事
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1;
return T;
}
7.树的输出:
void Preorder(struct TreeNode*T){//先序遍历的输出
if(T!=NULL){
printf("%d ",T->Data);先输出根
Preorder(T->Left);再输出左子树
Preorder(T->Right);最后输出右子树
}
}
如果是中序输出和后序输出,只需要将输出顺序改变即可
8.二叉树的结点数:
Int T1Count(struct TreeNode*T1){
If(T1==NULL)
return 0;
Else
return 1+T1Count(T1->Left)+T1Count(T1->Right);
}
9.计算AVL树的结点数:
Int AVLCount(struct AVLNode*T){
If(T==NULL)
return 0;
Else
return 1+AVLCount(T->Left)+AVLCount(T->Right);
}
10.计算二叉树的层次总和:
int DLCount(struct TreeNode*T1){//计算二叉树层次总和
if(T1==NULL){
return 0;
}
return DLCount(T1->Left)+DLCount(T1->Right)+T1Count(T1);
}
11.计算AVL树的层次总和:
int DACount(struct AVLNode*T){//计算AVL树层次总和
if(T==NULL){
return 0;
}
return DACount(T->Left)+DACount(T->Right)+AVLCount(T);
}
12.关于ASL的计算:
ASL=结点层次总和/结点总数
13.关于陈胜随机数并插入二叉树和AVL树中:
srand((int)time(NULL));
for(i=0;i<3;i++){
// j=(rand()<<15)|rand();
// scanf("%d",&j);
T1=Insert(T1,(rand()<<15)|rand());
T=InsertAVL(T,(rand()<<15)|rand());
}
关于源代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
struct TreeNode { //二叉树结构体
int Data;
int Height;
struct TreeNode * Left;
struct TreeNode * Right;
};
struct AVLNode{ //AVL树结构体
int Data;
int Height;
struct AVLNode * Left;
struct AVLNode * Right;
};
struct TreeNode*Insert(struct TreeNode*T1,int x){//二叉树中插入
if(T1==NULL){
T1=(struct TreeNode*)malloc(sizeof(struct TreeNode));
T1->Data=x;
T1->Height=0;
T1->Left=NULL;
T1->Right=NULL;
}else if(x<T1->Data){
T1->Left=Insert(T1->Left,x);
}else{
T1->Right=Insert(T1->Right,x);
}
return T1;
}
int Max(int a,int b){
return a>b?a:b;
}
int T1Height(struct TreeNode*T1){//二叉树高度
if(T1==NULL){
return 0;
}
else{
return 1+Max(T1Height(T1->Left),T1Height(T1->Right));
}
}
int GetHeight(struct AVLNode*T){//AVL树高度
if(T==NULL){
return 0;
}
else{
return 1+Max(GetHeight(T->Left),GetHeight(T->Right));
}
}
struct AVLNode* SLR(struct AVLNode * K2) {//左单旋
struct AVLNode *K1;
K1 = K2->Left;
K2->Left = K1->Right;
K1->Right = K2;
// 旋转完后更新K1、K2的高度
K2->Height = Max(GetHeight(K2->Left), GetHeight(K2->Right)) + 1;
K1->Height = Max(GetHeight(K1->Left), K2->Height) + 1;
return K1;
}
struct AVLNode * SRR(struct AVLNode *K1) {//右单旋
struct AVLNode *K2;
K2 = K1->Right;
K1->Right = K2->Left;
K2->Left = K1;
// 旋转完后更新K1、K2的深度
K1->Height = Max(GetHeight(K1->Left), GetHeight(K1->Right)) + 1;
K2->Height = Max(K1->Height, GetHeight(K2->Right)) + 1;
return K2;
}
struct AVLNode * DLR(struct AVLNode * K2)//左双旋
{
K2->Left = SRR(K2->Left);
return SLR(K2);
}
struct AVLNode * DRR(struct AVLNode * K1)//右双旋
{
K1->Right = SLR(K1->Right);
return SRR(K1);
}
struct AVLNode * InsertAVL(struct AVLNode * T, int X) {//AVL树的插入
if (T == NULL) {
T = (struct AVLNode*)malloc(sizeof(struct AVLNode));
T->Data = X;
T->Height = 1;
T->Left = T->Right = NULL;
} else if (X < T->Data) {
T->Left = InsertAVL(T->Left, X);
if (GetHeight(T->Left) - GetHeight(T->Right) == 2)
if (X < T->Left->Data)
T = SLR(T);
else
T = DLR(T);
} else if (X > T->Data) {
T->Right = InsertAVL(T->Right, X);
if (GetHeight(T->Right) - GetHeight(T->Left) == 2)
if (X > T->Right->Data)
T = SRR(T);
else
T = DRR(T);
}
// else X == T->Data的情况,不做任何事
T->Height = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1;
return T;
}
int T1Count(struct TreeNode*T1){// 二叉树的结点总数
if(T1==NULL){
return 0;
}
return 1+T1Count(T1->Left)+T1Count(T1->Right);
}
int AVLCount(struct AVLNode*T){//AVL树的结点总数
if(T==NULL){
return 0;
}
return 1+AVLCount(T->Left)+AVLCount(T->Right);
}
int DLCount(struct TreeNode*T1){//计算二叉树层次总和
if(T1==NULL){
return 0;
}
return DLCount(T1->Left)+DLCount(T1->Right)+T1Count(T1);
}
int DACount(struct AVLNode*T){//计算AVL树层次总和
if(T==NULL){
return 0;
}
return DACount(T->Left)+DACount(T->Right)+AVLCount(T);
}
int main(){
int i,j;
struct TreeNode*T1;
struct AVLNode*T;
T=NULL;
T1=NULL;
srand((int)time(NULL));
for(i=0;i<6;i++){
// j=(rand()<<15)|rand();
// scanf("%d",&j);
T1=Insert(T1,(rand()<<15)|rand());
T=InsertAVL(T,(rand()<<15)|rand());
}
printf("二叉排序树的结点数:");int x=T1Count(T1);printf("%d",x);
printf("\n");
printf("AVL的结点数:");int y=AVLCount(T);printf("%d",y);
printf("\n");
printf("二叉排序树的结点层数之和:");printf("%d",DLCount(T1));
printf("\n");
printf("AVL的结点层数之和:");printf("%d",DACount(T));
printf("\n");
printf("二叉排序树的ASL:");printf("%.2f",(float)DLCount(T1)/(float)T1Count(T1));
printf("\n");
printf("AVL树的ASL:");printf("%.2f",(float)DACount(T)/(float)AVLCount(T));
return 0;
}
实验结果:
完结撒花!!!!!!!!!!!!!!!!!!!!!!!