AVL树读书笔记

         最近开始了自己高级数据结构之旅,在这次旅行中,我将持续把一些高级的数据结构从理论到编码都过一遍,同时通过博客形式分享出来,希望大家指出不足之处!
     二叉排序树是一种动态排序的数据结构,支持插入、删除、查找等操作,且平均时间复杂度为O(log(N)),但是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N)。此时,平衡二叉树的产生了。平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树很难,于是人们使用AVL、红黑树、Treap、伸展树等来替代平衡二叉树,这些数据结构可以很好地改善最坏情况。但实现起来并不是很容易的事。

      AVL树是一种高度平衡的二叉查找树,但不是严格意义上的平衡二叉查找树。但AVL树实现相对简单,这里指相对简单。查、插入、删除、修改等基本操作时间复杂度均为O(log(N)),此处指所有情况下(包括平均、最好、最坏)。一般情况下AVL树要维护一个平衡因子,但在实现时可以直接用高度避免节点所占空间变大。

调整

          主要有两种操作,左旋LeftRotate、右旋RightRotate,在此基础上衍生出先左后右旋转LeftAndRightRotate,先右后左旋转RightAndLeftRotate。具体要视情况调整,下面是说明每种情况使用的场合。

(1)、左旋LeftRotate:2==当前节点右子树高度-当前节点左子树高度,并且右子树的右孩子节点高度大于右子树的左孩子节点高度,直接左旋。如图所示:

                       AVL树读书笔记_第1张图片

(2)、右旋RightRotate:-2==当前节点右子树高度-当前节点左子树高度,并且左子树的左孩子节点高度大于左子树的右孩子节点高度,直接左旋。如图所示:

                      AVL树读书笔记_第2张图片

(3)、先左后右旋转LeftAndRightRotate-2==当前节点右子树高度-当前节点左子树高度,并且左子树的左孩子节点高度小于左子树的右孩子节点高度,直接左旋。如图所示:

                                AVL树读书笔记_第3张图片

(4)、先右后左旋转RightAndLeftRotate:2==当前节点右子树高度-当前节点左子树高度,并且右子树的右孩子节点高度小于右子树的左孩子节点高度,直接左旋。如图所示:

                       AVL树读书笔记_第4张图片

 

插入

      在插入一个元素以后,很有可能不再平衡,此时需要调整平衡。可以从不在平衡的最底层节点开始,依据调整规则旋转,然后一次上调,这样最终就能保证处于平衡状态。此过程时间复杂度为O(log(N)),不将会出现极端情况。由于之前是平衡的,所以不平衡因素必定在根节点到当前插入节点的路径上,故只需调整此路径即可。

 

删除

     要删除一个元素,可能有两种情况需要考虑,如下:

    A、如果该元素所在节点没有右孩子节点,直接删除;

    B、如果有右孩子,需找到右孩子所在子树的最大元素,用其替代本应删除节点元素,剩下就转到删除该右子树最小元素节点。当然可以找到左子树最大元素节点替代,只是1中条件也应相应的改变。

     在删除一个元素后,很有可能不再平衡,此时需要调整平衡。可以从不在平衡的最底层节点开始,依据调整规则旋转,然后一次上调,这样最终就能保证处于平衡状态。此过程时间复杂度为O(log(N)),不将会出现极端情况。由于之前是平衡的,所以不平衡因素必定在根节点到当前插入节点的路径上,故只需调整此路径即可。

 

修改

     修改在前面已有插入、删除的基础上就相对简单了,只需首先删除旧元素,然后插入新元素,时间复杂度为O(log(N))。由于转换成了先删除后插入的操作,所以能保证平衡。

 

源程序代码

//AVLTreeNode.h头文件,定义节点信息
#include<iostream>
using namespace std;

/**********************************
*功能:防止头文件多次包含
**********************************/
#ifndef AVLTREENODE_H
#define AVLTREENODE_H


struct AVLTreeNode
{
	int key;
	int height;
	AVLTreeNode *leftChild;
	AVLTreeNode *rightChild;
	AVLTreeNode(int tempKey)
	{
		height=0;
		key=tempKey;
		leftChild=NULL;
		rightChild=NULL;
	}
};

#endif AVLTREENODE_H
//AVLTree.cpp源文件,完成AVL树的基本操作
#include<iostream>
#include<algorithm>
#include"AVLTreeNode.h"
using namespace std;

class AVLTree
{
private:
	AVLTreeNode *root;
	AVLTreeNode *Search(int,AVLTreeNode *);
	AVLTreeNode *LeftRotate(AVLTreeNode *);
	AVLTreeNode *LeftAndRightRotate(AVLTreeNode *);
	AVLTreeNode *RightRotate(AVLTreeNode *);
	AVLTreeNode *RightAndLeftRotate(AVLTreeNode *);
	int GetHeight(AVLTreeNode *);
	void PreOrderPrint(AVLTreeNode *);
	void InOrderPrint(AVLTreeNode *);
	void SufOrderPrint(AVLTreeNode *);
	void RotatePrint(AVLTreeNode *,int);
	AVLTreeNode *Insert(int,AVLTreeNode *);
	AVLTreeNode *Delete(bool&,int,AVLTreeNode *);
public:
	AVLTree();
	void Insert(int);
	bool Search(int);
	bool Delete(int);
	bool Updata(int,int);
	void PreOrderPrint();
	void InOrderPrint();
	void SufOrderPrint();
	void RotatePrint();
};


AVLTree::AVLTree()
{
	root=NULL;
}

/*********************************************
*参数:当前节点
*返回值:当前节点高度
*功能:返回当前节点高度
**********************************************/
int AVLTree::GetHeight(AVLTreeNode *tempNode)
{
	return NULL==tempNode?-1:tempNode->height;
}

/*********************************************
*参数:待查找元素,当前节点
*返回值:元素所在节点
*功能:返回元素所在节点
**********************************************/
AVLTreeNode *AVLTree::Search(int tempKey,AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return NULL;
	else if(tempKey==tempNode->key)
		return tempNode;
	else if(tempKey<tempNode->key)
		return Search(tempKey,tempNode->leftChild);
	return Search(tempKey,tempNode->rightChild);
}
bool AVLTree::Search(int tempKey)
{
	if(NULL==Search(tempKey,root))
		return false;
	return true;
}

/*********************************************
*参数:当前节点
*返回值:当前子树根节点
*功能:左旋调平衡
**********************************************/
AVLTreeNode *AVLTree::LeftRotate(AVLTreeNode *tempNode)
{
	AVLTreeNode *lChildNode=tempNode->rightChild->leftChild,*newRoot=tempNode->rightChild;
	tempNode->rightChild->leftChild=tempNode;
	tempNode->rightChild=lChildNode;
	tempNode->height=max(GetHeight(tempNode->leftChild),GetHeight(tempNode->rightChild))+1;
	if(NULL!=tempNode->rightChild)
		tempNode->rightChild->height=max(GetHeight(tempNode->rightChild->leftChild),GetHeight(tempNode->rightChild->rightChild))+1;
	return newRoot;
}

/*********************************************
*参数:当前节点
*返回值:当前子树根节点
*功能:右旋调平衡
**********************************************/
AVLTreeNode *AVLTree::RightRotate(AVLTreeNode *tempNode)
{
	AVLTreeNode *rChildNode=tempNode->leftChild->rightChild,*newRoot=tempNode->leftChild;
	tempNode->leftChild->rightChild=tempNode;
	tempNode->leftChild=rChildNode;
	tempNode->height=max(GetHeight(tempNode->leftChild),GetHeight(tempNode->rightChild))+1;
	if(NULL!=tempNode->leftChild)
		tempNode->leftChild->height=max(GetHeight(tempNode->leftChild->leftChild),GetHeight(tempNode->leftChild->rightChild))+1;
	return newRoot;
}

/*********************************************
*参数:当前节点
*返回值:当前子树根节点
*功能:先左旋后右旋调平衡
**********************************************/
AVLTreeNode *AVLTree::LeftAndRightRotate(AVLTreeNode *tempNode)
{
	tempNode->leftChild=LeftRotate(tempNode->leftChild);
	return RightRotate(tempNode);
}

/*********************************************
*参数:当前节点
*返回值:当前子树根节点
*功能:先右旋后左旋调平衡
**********************************************/
AVLTreeNode *AVLTree::RightAndLeftRotate(AVLTreeNode *tempNode)
{
	tempNode->rightChild=RightRotate(tempNode->rightChild);
	return LeftRotate(tempNode);
}

/*********************************************
*参数:待插入元素,当前节点
*返回值:当前子树根节点
*功能:插入元素到当前节点的子树
**********************************************/
AVLTreeNode *AVLTree::Insert(int tempKey,AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return tempNode=new AVLTreeNode(tempKey);
	else 
	{
		if(tempKey==tempNode->key)
			return tempNode;
		else if(tempKey<tempNode->key)
			tempNode->leftChild=Insert(tempKey,tempNode->leftChild);
		else tempNode->rightChild=Insert(tempKey,tempNode->rightChild);
	}
	//tempNode->height=max(GetHeight(tempNode->leftChild),GetHeight(tempNode->rightChild))+1;
	if(2==GetHeight(tempNode->leftChild)-GetHeight(tempNode->rightChild))
	{
		if(tempKey<tempNode->leftChild->key)
			tempNode=RightRotate(tempNode);
		else tempNode=LeftAndRightRotate(tempNode);
	}
	else if(-2==GetHeight(tempNode->leftChild)-GetHeight(tempNode->rightChild))
	{
		if(tempKey>tempNode->rightChild->key)
			tempNode=LeftRotate(tempNode);
		else tempNode=RightAndLeftRotate(tempNode);
	}
	tempNode->height=max(GetHeight(tempNode->leftChild),GetHeight(tempNode->rightChild))+1;
	return tempNode;
}
void AVLTree::Insert(int tempKey)
{
	root=Insert(tempKey,root);
}

/*********************************************
*参数:待删除元素,当前节点
*返回值:当前子树根节点
*功能:删除元素
**********************************************/
AVLTreeNode *AVLTree::Delete(bool &isDelSucceed,int tempKey,AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return NULL;
	else 
	{
		if(tempKey==tempNode->key)
		{
			if(NULL==tempNode->rightChild)
			{
				AVLTreeNode *cur=tempNode;
				tempNode=tempNode->leftChild;
				delete cur;
				isDelSucceed=true;
				return tempNode;
			}
			else//找到右子树最小的元素代替,然后删除 
			{
				AVLTreeNode *cur=tempNode->rightChild;
				while(cur->leftChild!=NULL)
					cur=cur->leftChild;
				tempNode->key=cur->key;
				tempNode->rightChild=Delete(isDelSucceed,cur->key,tempNode->rightChild);
			}
		}
		else if(tempKey<tempNode->key)
			tempNode->leftChild=Delete(isDelSucceed,tempKey,tempNode->leftChild);
		else tempNode->rightChild=Delete(isDelSucceed,tempKey,tempNode->rightChild);
		
		if(-2==GetHeight(tempNode->leftChild)-GetHeight(tempNode->rightChild))//删除的是左子树上的
		{
			if(GetHeight(tempNode->rightChild->rightChild)>=GetHeight(tempNode->rightChild->leftChild))
				tempNode=LeftRotate(tempNode);
			else tempNode=RightAndLeftRotate(tempNode);
		}
		else if(2==GetHeight(tempNode->leftChild)-GetHeight(tempNode->rightChild))
		{
			if(GetHeight(tempNode->leftChild->leftChild)>=GetHeight(tempNode->leftChild->rightChild))
				tempNode=RightRotate(tempNode);
			else tempNode=LeftAndRightRotate(tempNode);
		}
		tempNode->height=max(GetHeight(tempNode->leftChild),GetHeight(tempNode->rightChild))+1;
	}
	return tempNode;
}
bool AVLTree::Delete(int tempKey)
{
	bool isDelSucceed=false;
	root=Delete(isDelSucceed,tempKey,root);
	return isDelSucceed;
}

/**********************************************************
*参数:待修改节点元素、修改后的元素
*返回值:返回修改是否成功
*功能:修改函数
************************************************************/
bool AVLTree::Updata(int oldKey,int newKey)
{
	if(Delete(oldKey))
	{
		Insert(newKey);
		return true;
	}
	return false;
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:前序遍历二叉查找树
************************************************************/
void AVLTree::PreOrderPrint(AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return ;
	cout<<tempNode->key<<"    ";
	PreOrderPrint(tempNode->leftChild);
	PreOrderPrint(tempNode->rightChild);
}
void AVLTree::PreOrderPrint()
{
	PreOrderPrint(this->root);
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:中序遍历二叉查找树
************************************************************/
void AVLTree::InOrderPrint(AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return ;
	InOrderPrint(tempNode->leftChild);
	cout<<tempNode->key<<"   ";
	InOrderPrint(tempNode->rightChild);
}
void AVLTree::InOrderPrint()
{
	InOrderPrint(root);
}

/**********************************************************
*参数:当前子树根节点
*返回值:空
*功能:后序遍历二叉查找树树
************************************************************/
void AVLTree::SufOrderPrint(AVLTreeNode *tempNode)
{
	if(NULL==tempNode)
		return ;
	SufOrderPrint(tempNode->leftChild);
	SufOrderPrint(tempNode->rightChild);
	cout<<tempNode->key<<"    ";
}
void AVLTree::SufOrderPrint()
{
	SufOrderPrint(root);
}

/**********************************************************
*参数:当前子树根节点,缩进列数
*返回值:空
*功能:翻转打印AVL树
************************************************************/
void AVLTree::RotatePrint(AVLTreeNode *tempNode,int tempColumn)
{
	if(NULL==tempNode)
		return ;
	RotatePrint(tempNode->leftChild,tempColumn+1);
	for(int i=0;i<tempColumn;i++)
		cout<<"    ";
	cout<<"---"<<tempNode->key<<endl;
	RotatePrint(tempNode->rightChild,tempColumn+1);
}
void AVLTree::RotatePrint()
{
	RotatePrint(root,0);
}

void Menu()
{
	int val,choice,newVal;
	AVLTree myAVLTree;
	while(true)
	{
		do
		{
			cout<<"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"<<endl;
			cout<<"       1.插入"<<endl;
			cout<<"       2.删除"<<endl;
			cout<<"       3.修改"<<endl;
			cout<<"       4.查找"<<endl;
			cout<<"       5.显示"<<endl;
			cout<<"       6.返回"<<endl;
			cout<<"请输入你的选项[ ]\b\b";
			cin>>choice; 
		}while(choice!=1&&choice!=2&&choice!=3&&choice!=4&&choice!=5&&choice!=6);
		if(1==choice)
		{
			cin>>val;
			myAVLTree.Insert(val);
		}
		else if(2==choice)
		{
			cin>>val;
			if(myAVLTree.Delete(val))
				cout<<"删除成功!"<<endl;
			else cout<<"删除失败!"<<endl;
		}
		else if(3==choice)
		{
			cin>>val>>newVal;
			if(myAVLTree.Updata(val,newVal))
				cout<<"修改成功!"<<endl;
			else cout<<"修改失败!"<<endl;
		}
		else if(4==choice)
		{
			cin>>val;
			if(NULL!=myAVLTree.Search(val))
				cout<<"查找成功!"<<endl;
			else cout<<"查找失败!"<<endl;
		}
		else if(5==choice)
		{
			cout<<endl<<"*****************************"<<endl;
			cout<<endl<<"==========前序=============="<<endl;
			myAVLTree.PreOrderPrint();
			cout<<endl<<"==========中序================"<<endl;
			myAVLTree.InOrderPrint();
			cout<<endl<<"==========后续==============="<<endl;
			myAVLTree.SufOrderPrint();
			cout<<endl<<"==========对称+旋转==============="<<endl;
			myAVLTree.RotatePrint();
			cout<<endl<<"*****************************"<<endl;
		}
		else return ;
	}
}

int main()
{
	while(true)
		Menu();
	return 0;
}

 

      上面是我的源代码,可能有很多不合理的地方,欢迎斧正!

 

 

 

 

你可能感兴趣的:(avl树,平衡二叉查找树)