平衡二叉树插入的实现

 向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成

 

头文件AvlTree.h

#ifndef AVLTREE_H
#define AVLTREE_H
typedef int Element;
typedef struct Node{
	Element data;
	struct Node *left,*right;
	int Height;		//节点的高度
}AvlNode,*AvlTree,*Position;
void MakeEmpty(AvlTree &T); //清空平衡二叉搜索树
bool IsEmpty(AvlTree T); //判断树是否为空
bool Find(Element x,AvlTree T); //查找元素
Position FindMin(AvlTree T); //查找最小元素
Position FindMax(AvlTree T); //查找最大元素
AvlTree Insert(Element x,AvlTree &T); //插入元素
Position SingleRotateWithLeft(AvlTree k2); //向左单旋转
Position SingleRotateWithRight(AvlTree k2); //向右单旋转
Position DoubleRotateWithLeft(AvlTree k3); //双旋转
Position DoubleRotateWithRight(AvlTree k3); //双旋转
int MAX(int a,int b); 
int Height(Position p); //返回节点的高度
void InOrderTraverse(AvlTree T); //前序遍历树
#endif //AVLTREE_H


实现文件AvlTree.cpp

#include "AvlTree.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void MakeEmpty(AvlTree &T) //清空树
{
	if(T == NULL)
		return;
	MakeEmpty(T->left);
	MakeEmpty(T->right);
	free(T);
	T = NULL;
}
bool IsEmpty(AvlTree T) 
{
	return T == NULL ? true : false;
}
bool Find(Element x,AvlTree T)
{
	if(T == NULL)
		return false;
	else if(x < T->data)  //如果元素小于当前节点往左继续查找
		return Find(x,T->left);
	else if(x > T->data) //如果元素大于当前节点往右继续查找
		return Find(x,T->right);
	return true;
}
Position FindMin(AvlTree T) //查找最小值
{
	if(T == NULL)
		return NULL;
	else if(T->left == NULL) //节点的左子树为NULL,此节点就是最小元素的节点
		return T;
	else
		FindMin(T->left);
}
Position FindMax(AvlTree T)
{
	if(T == NULL)
		return NULL;
	else if(T->right == NULL) //节点的右子树为NULL,此节点就是最大元素的节点
		return T;
	else
		FindMax(T->right);
}
AvlTree Insert(Element x,AvlTree &T)
{
	if(T == NULL) //创建节点
	{
		T = (AvlTree)malloc(sizeof(AvlNode));
		if(T == NULL)
		{
			printf("内存分配失败,程序即将退出\n");
			exit(1);
		}
		T->data = x;
		T->Height = 0;
		T->left = T->right = NULL;
	}
	else if(x < T->data) //元素小于当前节点的元素,往左继续
	{
		T->left = Insert(x,T->left);
		if(Height(T->left) - Height(T->right) == 2) //如果左边节点的高度比右边节点的高度大2
			if(x < T->left->data)					//且元素x小于左边的元素,也就是x插入的方向是左边
				T = SingleRotateWithLeft(T);        //执行单旋转
			else
				T = DoubleRotateWithLeft(T);        //执行双旋转
	}
	else if(x > T->data)
	{
		T->right = Insert(x,T->right);
		if(Height(T->right) - Height(T->left) == 2)
			if(x > T->right->data)
				T = SingleRotateWithRight(T);
			else
				T = DoubleRotateWithRight(T);
	}
	T->Height = MAX(Height(T->left),Height(T->right)) + 1; //计算在节点插入后的各节点的高度
	return T;
}
Position SingleRotateWithLeft(AvlTree k2) //单旋转
{
	Position k1 = k2->left;
	k2->left = k1->right;
	k1->right = k2;
	k2->Height = MAX(Height(k2->left),Height(k2->right)) + 1;
	k1->Height = MAX(Height(k1->left),k2->Height) + 1;
	return k1;
}
Position SingleRotateWithRight(AvlTree k2)
{
	Position k1 = k2->right;
	k2->right = k1->left;
	k1->left = k2;
	k2->Height = MAX(Height(k2->left),Height(k2->right)) + 1;
	k1->Height = MAX(Height(k1->right),k2->Height);
	return k1;
}
Position DoubleRotateWithLeft(AvlTree k3) //双旋转
{
	k3->left = SingleRotateWithRight(k3->left);
	return SingleRotateWithLeft(k3);
}
Position DoubleRotateWithRight(AvlTree k3)
{
	k3->right = SingleRotateWithLeft(k3->right);
	return SingleRotateWithRight(k3);
}
int Height(Position p)
{
	return p == NULL ? -1 : p->Height;
}
int MAX(int a,int b)
{
	return a > b ? a : b;
}
void InOrderTraverse(AvlTree T) //前序遍历
{
	if(T)
	{
		printf("%d ",T->data);
		InOrderTraverse(T->left);
		InOrderTraverse(T->right);
	}
}


测试文件main.cpp

#include "AvlTree.h"
#include <stdio.h>
int main()
{
	AvlTree T = NULL;
	int it;
	printf("请输入平衡二叉搜索树的数据\n");
	while(scanf("%d",&it) != EOF)
		Insert(it,T);
	printf("平衡二叉搜索树的数据为:\n");
	InOrderTraverse(T);
	printf("\n");
	printf("平衡二叉搜索树的最小元素为:%d\n",FindMin(T)->data);
	printf("平衡二叉搜索树的最大元素为:%d\n",FindMax(T)->data);
	printf("请输入要查找的内容\n");
	scanf("%d",&it);
	if(Find(it,T))
		printf("在平衡二叉搜索树中找到元素%d\n",it);
	else
		printf("在平衡二叉搜索树中未找到元素%d\n",it);
	MakeEmpty(T);
	if(IsEmpty(T))
		printf("平衡二叉搜索树为空\n");
	return 0;
}


 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值