AVL树详解

AVL树定义:

AVL树又称为高度平衡的二叉搜索树。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。

AVL树性质:

  1. 左子树和右子树的高度之差的绝对值不超过1
  2. 树中的每个左子树和右子树都是AVL树
  3. 每个节点都有一个平衡因子(balance factor–bf),任一节点的平衡因子是-1,0,1。(每个节点的平衡因子等于右子树的高度减去左子树的高度 )   

AVL树效率:
一棵AVL树有N个节点,其高度可以保持在lgN,插入/删除/查找的时间复杂度也是lgN。


AVL树节点信息如下:

template<class K, class V>
struct AVLTreeNode
{
	K _key;  //关键字
	V _value; 

	AVLTreeNode<K, V>* _parent;//父亲
	AVLTreeNode<K, V>* _left;//左孩子
	AVLTreeNode<K, V>* _right;//右孩子

	int _bf;//平衡因子
	AVLTreeNode<K, V>(const K& key, const V& value)//构造函数
		: _key(key)
		, _value(value)
		, _parent(NULL)
		, _left(NULL)
		, _right(NULL)
		, _bf(0)
	{}
};



AVL树操作包括:插入,查找,删除等。
由于AVL树要求左右子树高度差的绝对值不超过1,因此AVL树必须通过旋转调平衡因子保持平衡


插入:先插入节点再调平衡因子。

1、插入节点:

(1)若AVL树为空则new一个节点作为根节点;

        (2)若要插入的节点等于根节点,返回false;

        (3)若要插入的节点大于根节点,递归右子树插入节点,反之递归左子树插入节点。

2、调平衡因子(通过旋转)


《AVL树详解》

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

		if (subRL)
		{
			subRL->_parent = parent;
		}

		subR->_left = parent;
		subR->_parent = parent->_parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		//更新节点信息
		if (ppNode == NULL)
		{
			_root = subR;
			subR->_parent = NULL;
		}
		else if (ppNode->_left == parent)
		{
			ppNode->_left = subR;
		}
		else
		{
			ppNode->_right = subR;
		}
		subR->_parent = ppNode;
		parent->_bf = subR->_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;
		subL->_parent = parent->_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;
		parent->_bf = subL->_bf = 0;//更新平衡因子
	}

《AVL树详解》





《AVL树详解》



查找:

1、若搜索树为空则返回空;

        2、若要查找的节点等于根节点,返回根节点;

        3、若要查找的节点大于根节点,递归查找右子树,反之递归查找左子树。

Node* Find(const K& key)
	{
		if (_root == NULL)
		{
			return NULL;
		}
		if (key > _root->_key)
		{
			_root = _root->_right;
		}
		else if (key < _root->_key)
		{
			_root = _root->_left;
		}
		else
		{
			return _root;
		}
		return NULL;
	}

此外还有删除操作,先删除节点再调平衡因子。删除方法和搜索二叉树删除方法(http://blog.csdn.net/wanglelelihuanhuan/article/details/51585941)一样

完整代码如下:

AVLTree.h

#include<math.h>

template<class K, class V>
struct AVLTreeNode
{
	K _key;  //关键字
	V _value; 

	AVLTreeNode<K, V>* _parent;//父亲
	AVLTreeNode<K, V>* _left;//左孩子
	AVLTreeNode<K, V>* _right;//右孩子

	int _bf;//平衡因子
	AVLTreeNode<K, V>(const K& key, const V& value)//构造函数
		: _key(key)
		, _value(value)
		, _parent(NULL)
		, _left(NULL)
		, _right(NULL)
		, _bf(0)
	{}
};

template<class K, class V>
class AVLTree
{
	typedef AVLTreeNode<K, V> Node;
public:
	AVLTree()
		:_root(NULL)
	{}
	Node* Find(const K& key)
	{
		if (_root == NULL)
		{
			return NULL;
		}
		if (key > _root->_key)
		{
			_root = _root->_right;
		}
		else if (key < _root->_key)
		{
			_root = _root->_left;
		}
		else
		{
			return _root;
		}
		return NULL;
	}
	bool Insert(const K& key,const V& value)
	{
		//先插入节点
		if (_root == NULL)
		{
			_root = new Node(key, value);
			return true;
		}
		Node* parent = NULL;
		Node* cur = _root;
		while (cur)
		{
			if (key > cur->_key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (key < cur->_key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key, value);
		if (key > parent->_key)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		
		//再调平衡因子
		while (parent)
		{
			if (parent->_left == cur)
			{
				parent->_bf--;
			}
			else
			{
				parent->_bf++;
			}

			if (parent->_bf == 0)  //已经是平衡树
			{
				break;
			}
			else if (parent->_bf == -1 || parent->_bf == 1) //继续回溯
			{
				cur = parent;
				parent = cur->_parent;
			}
			else // -2  2  调整 旋转
			{
				if (parent->_bf == 2)
				{
					if (cur->_bf == 1)  //  '\'   左单旋  
					{
						_RotateL(parent);
					}
					else  //-1   '>' 右左双旋
					{
						_RotateRL(parent);
					}
				}
				else  //-2
				{
					if (cur->_bf == -1)  // '/' 右单旋
					{
						_RotateR(parent);
					}
					else   // '<' 左右双旋
					{
						_RotateLR(parent);
					}
				}
				break;
			}
		}
		return true;
	}
	void Inorder()
	{
		_Inorder(_root);
		cout << endl;
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}
protected:
	void _RotateL(Node*& parent)  // '\'  ->   '/\'
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		parent->_right = subRL;

		if (subRL)
		{
			subRL->_parent = parent;
		}

		subR->_left = parent;
		subR->_parent = parent->_parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		//更新节点信息
		if (ppNode == NULL)
		{
			_root = subR;
			subR->_parent = NULL;
		}
		else if (ppNode->_left == parent)
		{
			ppNode->_left = subR;
		}
		else
		{
			ppNode->_right = subR;
		}
		subR->_parent = ppNode;
		parent->_bf = subR->_bf = 0;//更新平衡因子
	}
	void _RotateR(Node*& parent)   // '/'  ->   '/\'
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		parent->_left = subLR;

		if (subLR)
		{
			subLR->_parent = parent;
		}

		subL->_right = parent;
		subL->_parent = parent->_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;
		parent->_bf = subL->_bf = 0;//更新平衡因子
	}
	void _RotateLR(Node*& parent)   //  '<'  ->   '/'  ->   '/\'
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		int bf = subLR->_bf;

		_RotateL(parent->_left);
		_RotateR(parent);

		if (bf == 1)
		{
			subL->_bf = -1;
			parent->_bf = 0;
		}
		else if (bf == -1)
		{
			subL->_bf = 0;
			parent->_bf = 1;
		}
		else
		{
			subL->_bf = parent->_bf = 0;
		}
		subLR->_bf = 0;
		
	}
	void _RotateRL(Node*& parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		
		int bf = subRL->_bf;
		_RotateR(parent->_right);
		_RotateL(parent);
		if (bf == 1)
		{
			subR->_bf = 0;
			parent->_bf = -1;
		}
		else if (bf == -1)
		{
			subR->_bf = 1;
			parent->_bf = 0;
		}
		else
		{
			subR->_bf = parent->_bf = 0;
		}
		subRL->_bf = 0;
	}
	int _Height(Node* root)
	{
		if (root == NULL)
		{
			return 0;
		}
		int Left = _Height(root->_left);
		int Right = _Height(root->_right);
		return (Left > Right ?  Left:Right)+1;
	}
	void _Inorder(Node* root)
	{
		if (root == NULL)
			return ;

		_Inorder(root->_left);
		cout << root->_key << " ";
		_Inorder(root->_right);
	}
	bool _IsBalance(Node*& root)
	{
		if (root == NULL)
		{
			return true;
		}
		int bf = _Height(root->_right) - _Height(root->_left) ;
		if (abs(bf) > 1 || bf != root->_bf)
		{
			cout << "平衡因子有问题:" << root->_key << endl;
			return false;
		}
		return _IsBalance(root->_left) && _IsBalance(root->_right);
	}
protected:
	Node* _root;
};

void TestInsert()
{
	int arr1[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	AVLTree<int, int> alt1;
	for (int i = 0; i < sizeof(arr1) / sizeof(arr1[0]); ++i)
	{
		alt1.Insert(arr1[i],i);
	}
	alt1.Inorder();
	cout << "isBlance? " << alt1.IsBalance() << endl;


	int arr[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16,14};
	AVLTree<int, int> alt2;
	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		alt2.Insert(arr[i], i);
	}
	alt2.Inorder();
	
	cout << "isBlance? " << alt2.IsBalance() << endl;
}

Test.cpp

#include<iostream>
using namespace std;

#include"AVLTree.h"

int main()
{
	TestInsert();
	return 0;
}


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