#ifndef AVLTREE_H_
#define AVLTREE_H_
#define FLOWOVER -1
struct AVLTreeADT;
typedef struct AVLTreeADT * AVLTree;//根指针,与节点指针本质一样
typedef struct AVLTreeADT * AVLNode;//节点指针
typedef int ElemType;//数据域数据类型
struct AVLTreeADT{
ElemType elem;//数据域
AVLTree left;//树节点左儿子指针
AVLTree right;//树节点右儿子指针
int height;//当前节点的高度,空节点为-1,只有本身的节点的高度为0
};
//辅助函数,返回输入节点的高度
static int Height(AVLNode N);
//辅助函数,返回输入两高度值中大的那一个
static int Max(int height_1, int height_2);
//辅助函数,有左儿子的单旋转,对N的左儿子的左子树进行一次插入后调用
static AVLNode SingleRotateWithLeft(AVLNode N);
//辅助函数,有右儿子的单旋转,对N的右儿子的右子树进行一次插入后调用
static AVLNode SingleRotateWithRight(AVLNode N);
//辅助函数,有左儿子的双旋转,对N的左儿子的右子树进行一次插入后调用
static AVLNode DoubleRotateWithLeft(AVLNode N);
//辅助函数,有右儿子的双旋转,对N的右儿子的左子树进行一次插入后调用
static AVLNode DoubleRotateWithRight(AVLNode N);
//清空树,返回根指针
AVLTree MakeEmpty(AVLTree T);
//在树中查找是否存在E,找到则返回true
bool Find(ElemType E, AVLTree T);
//查找树中的最小值,返回,若为空树,返回-1
ElemType FindMin(AVLTree T);
//查找树中的最大值,返回,若为空树,返回-1
ElemType FindMax(AVLTree T);
//向树T中插入E,返回根地址
AVLTree Insert(ElemType E, AVLTree T);
//从树T中删除E,返回根地址
AVLTree Delete(ElemType E, AVLTree T);
//检索,输入节点指针,返回该节点对应的节点的数据域
ElemType Retrieve(AVLNode N);
//中序遍历树B并打印,值域为空则输出0
void PrintTree(AVLTree T);
#endif
#include
#include
#include "AVLTree.h"
static int Height(AVLNode N)
{//static表示函数可见性仅为定义文件
if (N == NULL){
return -1;
}
else{
return N->height;
}
}
static int Max(int height_1, int height_2)
{
if (height_1 > height_2){
return height_1;
}
else{
return height_2;
}
}
static AVLNode SingleRotateWithLeft(AVLNode N)
{//图见课本P82、P88,结合图画一遍基本就能理解原理了
AVLNode leftSonOfN;
leftSonOfN = N->left;
N->left = leftSonOfN->right;
leftSonOfN->right = N;
N->height = Max(Height(N->left), Height(N->right));//重置节点深度
leftSonOfN->height = Max(Height(leftSonOfN->left), Height(leftSonOfN->right));
return leftSonOfN;
}
static AVLNode SingleRotateWithRight(AVLNode N)
{//图见课本P82、P88
AVLNode rightSonOfN;
rightSonOfN = N->right;
N->right = rightSonOfN->left;
rightSonOfN->left = N;
N->height = Max(Height(N->left), Height(N->right));//重置节点深度
rightSonOfN->height = Max(Height(rightSonOfN->left), Height(rightSonOfN->right));
return rightSonOfN;//返回新的树根
}
static AVLNode DoubleRotateWithLeft(AVLNode N)
{//图见课本P84、P89
N->left = SingleRotateWithRight(N->left); //以N->left为节点完成第一次单右旋转
return SingleRotateWithLeft(N); //以N为节点完成第二次单左旋转,并返回根节点
}
static AVLNode DoubleRotateWithRight(AVLNode N)
{//图见课本P84、P89
N->right = SingleRotateWithLeft(N->right);
return SingleRotateWithRight(N);
}
AVLTree MakeEmpty(AVLTree T)
{//唯一根节点T = NULL表示树为空
if (T != NULL){
MakeEmpty(T->left);
MakeEmpty(T->right);
free(T);
}
return NULL;
}
ElemType FindMin(AVLTree T)
{
if (T != NULL){
if (T->left == NULL){
return T->elem;
}
else{
return FindMin(T->left);//递归查找左子树的左子树,最小值一定在最左边
}
}
return -1;//树为空,返回-1
}
ElemType FindMax(AVLTree T)
{
if (T != NULL){
if (T->left == NULL){
return T->elem;
}
else{
return FindMax(T->right);//递归查找右子树的右子树,最大值一定在最右边
}
}
return -1;//树为空,返回-1
}
AVLTree Insert(ElemType E, AVLTree T)
{
if (T == NULL){
T = (AVLTree)malloc(sizeof(struct AVLTreeADT));
if (T == NULL)
exit(FLOWOVER);
else{
T->elem = E;
T->left = NULL;
T->right = NULL;
}
}
else if (E < T->elem){
T->left = Insert(E, T->left);//往左边插入,深度增加的必为左边
if (Height(T->left) - Height(T->right) == 2){
if (E < T->left->elem){
T = SingleRotateWithLeft(T);
}
else{
T = DoubleRotateWithLeft(T);
}
}
}
else if (E > T->elem){
T->right = Insert(E, T->right);
if (Height(T->right) - Height(T->left) == 2){
if (E > T->right->elem){
T = SingleRotateWithRight(T);
}
else{
T = DoubleRotateWithRight(T);
}
}
}
else{//重复插入,不做任何操作,直接返回
return T;
}
T->height = Max(Height(T->left), Height(T->right));//每次递归回退后更新节点高度
return T;
}
AVLTree Delete(ElemType E, AVLTree T)
{//删除的点可能不属于需要旋转的树,如何处理
if (T != NULL){//判断是否为空树
if (T->elem == E){//如果找到了
if (T->left == NULL || T->right == NULL){//没有子节点或只有一个子节点
AVLNode tempPtr = T;
if (T->right == NULL){//没有子节点或只有左节点
T = T->left;
free(tempPtr);
}
else if (T->left == NULL){//只有右节点
T = T->right;
free(tempPtr);
}
}
else{//有两个儿子,用其右子树中最小的数据代替该节点的数据,然后递归删除
T->elem = FindMin(T->right);
T->right = Delete(T->elem, T->right);//相当于用右子树中最小的节点覆盖删除节点,然后删除右子树中的那个节点
}
}
else if (E < T->elem){//如果没找到,继续搜索左子树
T->left = Delete(E, T->left);
T->height = Max(Height(T->left), Height(T->right));//每次递归回退后更新节点高度
if (Height(T->right) - Height(T->left) == 2){//若两子树高度差为2,则通过旋转修复
if (Height(T->right->left) > Height(T->right->right)){//通过子树的左右子树深度判断需要采用哪种修复方式
T = DoubleRotateWithRight(T);
}
else if (Height(T->right->left) < Height(T->right->right)){
T = SingleRotateWithRight(T);
}
else{//当子树的左右子树深度相同时,有可能会导致一次修复还不够,需要补充修复一次,具体自己画图可知
T = DoubleRotateWithRight(T);
if (Height(T->right->right) - Height(T->right->left) == 2){
T->right = SingleRotateWithRight(T->right);
}
}
}
}
else{//如果没找到,继续搜索右子树
T->right = Delete(E, T->right);
T->height = Max(Height(T->left), Height(T->right));//每次递归回退后更新节点高度
if (Height(T->left) - Height(T->right) == 2){
if (Height(T->left->left) > Height(T->left->right)){
T = SingleRotateWithLeft(T);
}
else if (Height(T->left->left) < Height(T->left->right)){
T = DoubleRotateWithLeft(T);
}
else{
T = DoubleRotateWithLeft(T);
if (Height(T->left->left) - Height(T->left->right) == 2){
T->left = SingleRotateWithLeft(T->left);
}
}
}
}
}
else{//空树,不做任何操作,直接回退
return T;
}
return T;
}
ElemType Retrieve(AVLNode N)
{
if (N != NULL){
return N->elem;
}
else
return -1;
}
void PrintTree(AVLTree T)
{
if (T == NULL){
printf("0 ");
}
else{
PrintTree(T->left);
printf("%d ", T->elem);
PrintTree(T->right);
}
}
#include
#include
#include
#include "AVLTree.h"
int main(){
srand((int)time(0));
AVLTree testTree = NULL;
while (1){
int a[20];//生成20个随机数存入树中
for (int i = 0; i < 20; i++){
int flag = 1;
a[i] = rand() % 100 + 1;
while (flag != 0 && i != 0){
for (int k = 0; k < i; k++){
if (a[k] == a[i]){
a[i] = rand() % 100 + 1;
break;
}
if (k == i - 1){
flag = 0;
}
}
}
testTree = Insert(a[i], testTree);
}
printf("testTree初始化为:");
PrintTree(testTree);
printf("\n");
int b[10];//生成十个不同的随机数,作为a[20]的下标
for (int i = 0; i < 10; i++){
b[i] = rand() % 20;
int flag = 1;
while (flag != 0 && i != 0){
for (int k = 0; k < i; k++){
if (b[k] == b[i]){
b[i] = rand() % 20;
break;
}
if (k == i - 1){
flag = 0;
}
}
}
}
for (int i = 0; i < 10; i++){//随机删除十个数,每删除一个打印一次
testTree = Delete(a[b[i]], testTree);
printf("删除%d后,testTree为:", a[b[i]]);
PrintTree(testTree);
printf("\n");
}
testTree = MakeEmpty(testTree);
system("pause");
}
}