花了一个上午的时间写的,先看了会书,在纸上划了划,感觉挺简单的,没想到实现起来还是有点难度的。路过的朋友评价评价代码质量怎么样。欢迎给出意见和批评,指出效率有待提高的地方。
问题描述部分
/*
Description
根据给出的整数序列,生成平衡二叉树,按要求输出平衡二叉树。
数据输入:
第一行是一个整数N(1<=N<=20),表示测试例子数。
以后每个测试例子的第一行是一个整数,M,表示整数序列的大小;第二行是整数序列。
数据输出:
输出测试例子的平衡二叉树,每个例子的平衡二叉树按广度优先遍历,
依次输出各节点值及左右子节点值,每个节点一行,如果子节点为空,输出#,
节点值和子节点值之间用一个空格隔开。例子之间使用0分行。
Sample Input
2
5
13 24 37 90 53
6
11 24 35 80 50 17
Sample Output
24 13 53
13 # #
53 37 90
37 # #
90 # #
0
24 11 50
11 # 17
50 35 80
17 # #
35 # #
80 # #
*/
分析部分:
/**
(1)LL 型:
新结点 X 插在 A 的左孩子的左子树里。调整方法见图
图中以 B 为轴心,将 A 结点从 B 的右上方转到 B 的右下侧,使 A 成为 B 的右孩子。
2 A 1 B
/ / \
1 B ----> 0 X A
/
0 X
(2)RR 型:
新结点 X 插在 A 的右孩子的右子树里。调整方法见图
图中以 B 为轴心,将 A 结点从 B 的左上方转到 B 的左下侧,使 A 成为 B 的左孩子。
2 A
\
1 B ----> B 1
\ / \
0 X A X 0
(3)LR 型:
新结点 X 插在 A 的左孩子的右子树里。调整方法见图
分为两步进行:第一步以 X 为轴心,将 B 从 X 的左上方转到 X 的左下侧,
使 B 成为 X 的左孩子, X 成为 A 的左孩子。第二步跟 LL 型一样处理(应以 X 为轴心)。
0 A A
/ /
1 B -----> X ----> X 1
\ / / \
2 X B B A 0
(4)RL 型:
新结点 X 插在 A 的右孩子的左子树里。调整方法见图
分为两步进行:第一步以 X 为轴心,将 B 从 X 的右上方转到 X 的右下侧,
使 B 成为 X 的右孩子, X 成为 A 的右孩子。第二步跟 RR 型一样处理 (应以 X 为轴心)。
0 A A
\ \
1 B -----> X ----> X 1
/ \ / \
2 X B A B 0
*/
代码实现部分
//头文件,函数,结构声明部分
#include <stdio.h>
#include <stdlib.h>
#define MAX 1000
//#define Max(a,b) (((a) < (b)) ? (b) : (a))
typedef struct AVLNode *AVLTree;
struct AVLNode
{
int data;
AVLTree lChild;
AVLTree rChild;
int height;
};
AVLTree insert(int , AVLTree );
int height(AVLTree);
void motifyHeight(AVLTree,AVLTree); //避免代码重复的修改高度函数
AVLTree singleRotateLeftLeft(AVLTree); //LL
AVLTree singleRotateRightRight(AVLTree); //RR
AVLTree doubleRotateLeftRight(AVLTree); //LR
AVLTree doubleRotateRightLeft(AVLTree); //RL
void createQueue(AVLTree,AVLTree *,int);
void printSortedBinaryTree(AVLTree *,int);
//主函数
int main()
{
AVLTree root = NULL;
int cases,n,input[MAX],i; //cases个用例,每个用例结点的个数
AVLTree queue[MAX];
scanf("%d",&cases);
while(cases--)
{
root = NULL;
scanf("%d",&n);
for(i=0; i<n; i++)
{
scanf("%d",&input[i]);
root = insert(input[i],root);
}
createQueue(root,queue,n);
printSortedBinaryTree(queue,n);
destoryNodes(queue,n); //记得释放申请过的内存空间是一个好的编程习惯
//最大限度的控制内存泄露问题
if(cases != 0)
{
printf("0\n");
}
}
system("pause");
return 0;
}
//求结点高度
int height(AVLTree p)
{
if (p == NULL)
return -1; //叶子结点的左右子树的高度为0
else
return p->height; //结点存在 直接返回该结点的height就行了
}
//插入结点操作
AVLTree insert(int x,AVLTree root)
{
if(root == NULL)
{
root = (AVLTree)malloc(sizeof(struct AVLNode));
root->data = x;
root->lChild = NULL;
root->rChild = NULL;
root->height = 0;
}
else if(x < root->data)
{
//插入到左子树
root->lChild = insert(x,root->lChild);
if(height(root->lChild) - height(root->rChild) == 2) //需要调整
{
//判断用哪种方式进行调整,能进入这里 x肯定是比root->data要小
//所以要么是LL型,要么是LR型
if(x < root->lChild->data) //说明是LL型
{
root = singleRotateLeftLeft(root);
}
else //说明是LR型
{
root = doubleRotateLeftRight(root);
}
}
}
else if(x > root->data)
{
//插入到右子树
root->rChild = insert(x,root->rChild);
if(height(root->rChild) - height(root->lChild) == 2) //需要调整
{
//判断用哪种方式进行调整,能进入这里 x肯定是比root->data要大
//所以要么是RR型,要么是RL型
if(x > root->rChild->data) //说明是RR型
{
root = singleRotateRightRight(root);
}
else
{
root = doubleRotateRightLeft(root); //RL型
}
}
}
//当root为叶子结点或者没有左子树,或者没有右子树时 用root->lChild->data这种方式就不行
//所以用一个函数求出高度,当没有左右子树为空时,左右子树的height为-1
root->height = max(height(root->lChild),height(root->rChild)) + 1;
return root;
}
//LL型
AVLTree singleRotateLeftLeft(AVLTree t)
{
/**
2 A 1 B
/ / \
1 B ----> 0 X A
/
0 X
*/
AVLTree pTemp;
pTemp = t->lChild;
pTemp->rChild = t;
t->lChild = NULL;
//重新调整A,B的高度
motifyHeight(t,pTemp);
return pTemp;
}
//RR型
//RR型
AVLTree singleRotateRightRight(AVLTree t)
{
/**
2 A
\
1 B ----> B 1
\ / \
0 X A X 0
*/
AVLTree pTemp;
pTemp = t-> rChild;
pTemp->lChild = t;
t->rChild = NULL;
//重新调整高度
motifyHeight(t,pTemp);
return pTemp;
}
//LR型
//LR型
AVLTree doubleRotateLeftRight(AVLTree t)
{
/**
* 0 A A
/ /
1 B -----> X ----> X 1
\ / / \
2 X B B A 0
*/
AVLTree pTemp;
t->lChild = singleRotateRightRight(t->lChild); //第一次转换
pTemp = singleRotateLeftLeft(t);
return pTemp;
}
//RL型
//RL型
AVLTree doubleRotateRightLeft(AVLTree t)
{
/**
0 A A
\ \
1 B -----> X ----> X 1
/ \ / \
2 X B A B 0
*/
t->rChild = singleRotateLeftLeft(t->rChild);
return singleRotateRightRight(t);
}
//用数组模拟队列,构建模拟队列
//用数组模拟队列
void createQueue(AVLTree root,AVLTree *queue,int n)
{
AVLTree pTemp = root;
int i,j;
i = 0;
j = 0;
if(pTemp != NULL)
{
queue[i++] = pTemp;
}
//构造模拟queue,当满n时退出
while(i != n)
{
if(pTemp->lChild != NULL)
{
queue[i++] = pTemp->lChild;
if(i == n)
{
break;
}
}
if(pTemp->rChild != NULL)
{
queue[i++] = pTemp->rChild;
if(i == n)
{
break;
}
}
pTemp = queue[++j];
}
}
//按格式打印结果
//按格式打印输出
void printSortedBinaryTree(AVLTree *queue,int n)
{
int i;
AVLTree pTemp;
for(i=0; i<n; i++)
{
pTemp = queue[i];
printf("%d ",pTemp->data);
if(pTemp->lChild != NULL)
{
printf("%d ",pTemp->lChild->data);
}
else
{
printf("# ");
}
if(pTemp->rChild != NULL)
{
printf("%d\n",pTemp->rChild->data);
}
else
{
printf("#\n");
}
}
}
//释放申请的内存空间
//释放申请的空间
void destoryNodes(AVLTree *queue,int n)
{
int i;
AVLTree pTemp;
for(i=0; i<n; i++)
{
pTemp = queue[i];
free(pTemp);
queue[i] = NULL;
}
}
完毕:提交结果AC.