高度平衡的二叉搜索树-----AVL树

AVL树是高度平衡的二叉搜索树,它能保持二叉树的高度平衡,尽可能降低二叉树的高度,减少数的平均搜索长度

AVL树的几个特点:

1.左右子树高度绝对值不超过1

2.树的每左右子树都是AVL树

3.每个节点的平衡因子是-1,0,1(平衡因子 = 右子树高度-左子树高度)

一棵AVL树有N个节点,其高度可以保持在log2N,插入/删除/查找的复杂度也在log2N(log2N就是以2为底N的对数)

AVL树通过不停的旋转达到它的特性

左单旋:

《高度平衡的二叉搜索树-----AVL树》

void _RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		//把subRL给父节点(parent),做其右节点
		parent->_right = subRL;
		if(subRL)//若subRL不为空,把它的父亲节点置为父节点(parent)
			subRL->_parent = parent;
		subR->_left = parent;
		Node* ppNode = parent->_parent;//
		parent->_parent = subR;//让subR成为中间那个节点(即父节点的父亲节点)

		if(ppNode == NULL)//父节点是根节点
		{
			_root = subR;
			_root->_parent = NULL;
		}
		else
		{
	//parent是ppNode的左孩子,则subR也成为ppNode的左孩子,parent是ppNode的右孩子,则subR也是ppNode的右孩子
			if(ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
				ppNode->_right = subR;
			subR->_parent = ppNode;
		}
		//完成旋转后,平衡因子变为0
		subR->_bf = parent->_parent->_bf = 0;
	}

右单旋:

《高度平衡的二叉搜索树-----AVL树》

void _RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if(subLR)
			subLR->_parent = parent;
		subL->_right = parent;

		Node* ppNode = parent->_parent;
		parent->_parent = subL;
		if(ppNode == NULL)
		{
			_root = subL;
			subL->_parent = NULL;
		}
		else
		{
			if(ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
				ppNode->_right = subL;
			subL->_parent = ppNode;
		}
		subL->_bf = parent->_bf = 0;
	}

左右双旋:

《高度平衡的二叉搜索树-----AVL树》

特殊情况会涉及到平衡因子的调节

《高度平衡的二叉搜索树-----AVL树》


《高度平衡的二叉搜索树-----AVL树》

void _RotateLR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		int bf = subLR->_bf;

		_RotateL(subL);
		_RotateR(parent);

		if(bf == 1)
		{
			//subL只有一个左孩子,无右孩子,平衡因子为-1
			subL->_bf = -1;
			//subLR的右孩子成为了parent的左孩子,与原有的右孩子平衡,平衡因子为0
			parent->_bf = 0;
		}
		else if(bf == -1)
		{
			//subLR的左孩子成为subR的右孩子,平衡因为为0
			subL->_bf = 0;
			//parent只有一个右孩子,平衡因子为1
			parent->_bf = 1;
		}
		else
		{
			//subLR既有左孩子又有右孩子,subLR的左孩子成为subL的右孩子,sunLR的右孩子成为parent的左孩子,平衡因子都为0
			subLR->_bf = subL->_bf = parent->_bf = 0;
		}
	}

右左双旋:

《高度平衡的二叉搜索树-----AVL树》


《高度平衡的二叉搜索树-----AVL树》

《高度平衡的二叉搜索树-----AVL树》

	void _RotateRL(Node* parent)//右左双旋
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int bf = subRL->_bf;

		_RotateR(parent->_right);
		_RotateL(parent);
		
		//调节平衡因子
		if(bf == 1)//subRL的平衡因子为1时
		{
			//subRL只有一个右孩子,完成旋转后,subRL的右孩子成为subR的左孩子,subR本来有一个右孩子,左右孩子数相等平衡因子为0
			subR->_bf = 0;
			//parent节点右孩子为subR,完成旋转后,是将subRL的左孩子赋给他做他的右孩子,可是subRL平衡因子为1,无左孩子,则parent完成旋转后无右孩子,平衡因子为-1
			parent->_bf = -1;
		}
		else if(bf == -1)
		{
			//subR只有一个右孩子,左孩子subRL成为父亲节点后无左孩子,平衡因子为1
			subR->_bf = 1;
			//subRL的左孩子成为parent的右孩子,与parent本来有的左孩子平衡,平衡因子为0
			parent->_bf = 0;
		}
		else
		{
			//最后一种情况subRL既有左孩子又有右孩子,subRL的左孩子成为parent的右孩子,subRL的右孩子成为subR的左孩子,平衡因子都为0
			subRL->_bf = subR->_bf = parent->_bf = 0;
		}
	}


代码实现:

AVLTree.h

#pragma once

#include <iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
	K _key;
	V _value;
	int _bf;
	AVLTreeNode<K,V>* _left;
	AVLTreeNode<K,V>* _right;
	AVLTreeNode<K,V>* _parent;

	AVLTreeNode(const K& key,const V& value)
		:_key(key)
		,_value(value)
		,_bf(0)
		,_left(NULL)
		,_right(NULL)
		,_parent(NULL)
	{}
};

template<class K,class V>
struct AVLTree
{
	typedef AVLTreeNode<K,V> Node;
public:
	AVLTree()
		:_root(NULL)
	{}

	bool Insert(const K& key,const V& value)
	{
		//当根节点为空时
		if(_root == NULL)
		{
			_root = new Node(key,value);
			return true;
		}

		//寻找key值插入的位置
		Node* parent = NULL;
		Node* cur = _root;
		while(cur)
		{
			if(cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if(cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
				return false;
		}
		//把cur连接到树上
		cur = new Node(key,value);
		if(parent->_key > key)
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			 parent->_right = cur;
			 cur->_parent = parent;
		}

		//更新平衡因子 
		while(parent)
		{
			if(cur == parent->_left)
			{
				parent->_bf--;
			}
			else
				parent->_bf++;

			//旋转调节树和平衡因子
			if(parent->_bf == -1||parent->_bf == 1)
			{
				//往上查询父节点的平衡因子
				cur = parent;
				parent = cur->_parent;

			}
			else if(parent->_bf == 0)
				break;
			else		//parent->_bf == 2||parent->_bf == -2
			{
				if(parent->_bf == 2)
				{
					if(cur->_bf == 1)
						_RotateL(parent);//左单旋
					else	//cur->_bf == -1
						_RotateRL(parent);//右左双旋
				}
				if(parent->_bf == -2)		//parent->_bf == -2
				{
					if(cur->_bf == -1)
						_RotateR(parent);//右单旋
					else		//cur->_bf == 1
						_RotateLR(parent);//左右双旋
				}

				break;
			}
		}

	}
	void _RotateL(Node* parent);
	
	void _RotateR(Node* parent);

	void _RotateRL(Node* parent);

	void _RotateLR(Node* parent);
	
	bool IsBlance()
	{
		return _IsBlance(_root);
	}
	bool _IsBlance(Node* root)
	{
		//如果为空树,直接返回true
		if(root == NULL)
			return true;
		int left = Height(root->_left);
		int right = Height(root->_right);

		if(root->_bf != (right-left))//root的平衡因子等于右子树高度-左子树高度
		{
			cout<<root->_key<<endl;
			return false;
		}

		return abs(right-left)<2  //平衡因子为-1,0,1,绝对值小于2
			&&_IsBlance(root->_left)
			&&_IsBlance(root->_right);
	}

	int Height(Node* root)
	{
		if(root == NULL)
			return 0;
		int left = Height(root->_left);
		int right = Height(root->_right);

		return left>right ? left+1 : right+1;
	}
	void InOrderSort()
	{
		_InOrderSort(_root);
		cout<<endl;
	}


	void _InOrderSort(Node* root)
	{
		if(root == NULL)
			return;
		
		_InOrderSort(root->_left);
		cout<<root->_value<<" ";
		_InOrderSort(root->_right);
	}
private:
	Node* _root;
};

Test.cp

void Test()  
{  
    int arr[] = {4,2,6,1,3,5,15,7,16,14};  
    int size = sizeof(arr)/sizeof(arr[0]);  
  
    AVLTree<int,int> a;  
    int i = 0;  
    for (;i < size;i++)  
    {  
        a.Insert(arr[i],i);  
    }  
  
    cout<<a.IsBlance()<<endl;  
    a.InOrderSort();  
}  




《高度平衡的二叉搜索树-----AVL树》

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/z_xiao_xue/article/details/52622607
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞