平衡二叉搜索树

AVL树又称高度平衡的二叉搜索树,是1962年俄罗斯的数学家提出来的。它能保持二叉树的高度平衡,尽量降低二叉树的高度,减少树的平均搜索长度。

AVL的性质:

(1)左子树和右子树的高度之差的绝对值不超过1。

(2)树中的每个左子树和右子树都是AVL树。

(3)每个节点都有一个平衡因子,任一节点的平衡因子是-1,0,1(每个节点的平衡因子等于右子树的高度减去左子树的高度)。

代码实现如下:

#include<iostream>
using namespace std;

template<class K,class V>
struct AVLTreeNode{
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;

	K _key;
	V _value;
	int  _bf;   //平衡因子

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

template<class K,class V>
class 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;
		}
		Node* cur = _root;
		Node* parent = NULL;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		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 (parent->_right==cur)
				parent->_bf++;
			else
				parent->_bf--;
			//父节点平衡因子为0时,退出(说明父节点的两边高度一样,算路径长度的话都一样,没有影响)
			if (parent->_bf == 0)
				break;
			//父节点平衡因子为1或-1的时候(说明是从0+1或0-1得来的),父节点两边高度不同,故需要继续更新平衡因子
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				cur = parent;
				parent = cur->_parent;
			}
			//父节点平衡因子为2或-2时,旋转
			else  //(parent->_bf==2||parent->_bf==-2) 旋转
			{
				if (parent->_bf == -2)
				{
					if (cur->_bf == -1)//右单旋
					{
						_RotateR(parent);
					}
					else //(cur->_bf==1) 左右单旋
					{
						_RotateLR(parent);
					}
				}
				else //(parent->_bf==2)
				{
					if (cur->_bf == 1)  //左单旋
					{
						_RotateL(parent);
					}
					else  //(cur->_bf==-1)右左单旋
					{
						_RotateRL(parent);
					}
				}
				break;
			}
		}
	}
	Node* Find(const K& key)
	{
		if (_root == NULL)
			return false;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
				cur = cur->_left;
			else if (cur->_key < key)
				cur = cur->_right;
			else
				return cur;
		}
		return false;
	}
	bool Remove(const K& key)
	{
		if (_root == NULL)
			return false;

		Node* parent = NULL;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				Node* del;
				if (cur->_right == NULL)
				{
					del = cur;
					if (parent == NULL)
					{
						_root = cur->_left;
						//_root->_bf = 0;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_left;
							parent->_bf++;
						}
						else
						{
							parent->_right = cur->_left;
							parent->_bf--;
						}
					}
					delete del;
				}
				else if (cur->_left == NULL)
				{
					del = cur;
					if (parent == NULL)
					{
						_root = cur->_right;
						_root->_bf = 0;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_right;
							parent->_bf++;
						}
						else
						{
							parent->_right = cur->_right;
							parent->_bf--;
						}
					}
					delete del;
				}
				else
				{
					parent = cur;
					Node* left = cur->_right;
					while (left->_left)
					{
						parent = left;
						left = left->_left;
					}
					del = left;
					cur->_key = left->_key;
					cur->_value = left->_value;
					if (parent->_left == left)
					{
						parent->_left = left->_right;
						parent->_bf++;
					}
					else
					{
						parent->_right = left->_right;
						parent->_bf--;
					}

					delete del;
				}
				break;
			}
		}
		if (cur == NULL)
		{
			return false;
		}
		while (parent)
		{
			if (parent->_bf == 0)
			{
				break;
			}
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				break;
			}
			else //parent->_bf=2||parent->_bf=-2
			{
				if (parent->_bf == -2)
				{
					if (cur->_bf == -1)
						_RotateR(parent);
					else  //cur->_bf=1
						_RotateLR(parent);
				}
				else
				{
					if (cur->_bf == 1)
						_RotateL(parent);
					else
						_RotateRL(parent);
				}
				break;
			}
		}
		return true;
	}
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	//判断这棵树是否是平衡搜索树
	bool IsBlance()
	{
		return _IsBlance(_root);
	}
protected:
	void _RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR=subL->_right;

		parent->_left = subLR;
		if (subLR != NULL)
		{
			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;
				subL->_parent = ppNode;
			}
			else
			{
				ppNode->_right = subL;
				subL->_parent = ppNode;
			}
		}
		subL->_bf = parent->_bf = 0;
	}

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

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

		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		if (ppNode == NULL)
		{
			_root = subR;
			subR->_parent = NULL;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
				subR->_parent = ppNode;
			}
			else
			{
				ppNode->_right = subR;
				subR->_parent = ppNode;
			}
		}
		subR->_bf = parent->_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) //从subRL的右边插入
		{
			parent->_bf = -1;
			subR->_bf = 0;
		}
		else if (bf == -1) //从subRL的左边插入
		{
			parent->_bf = 0;
			subR->_bf = 1;
		}
		else    //(bf=0)
		{
			parent->_bf = 0;
			subR->_bf = 0;
		}
		subRL->_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)
		{
			parent->_bf = 0;
			subL->_bf = -1;
		}
		else if (bf == -1)
		{
			parent->_bf = 1;
			subL->_bf = 0;
		}
		else   //bf=0
		{
			parent->_bf = 0;
			subL->_bf = 0;
		}
		subLR->_bf = 0;
	}
	bool _IsBlance(Node* root)
	{
		if (root == NULL)
			return true;
		int right = _Height(root->_right);
		int left = _Height(root->_left);
		if (right - left != root->_bf || abs(right - left) >= 2)
		{
			cout << "平衡因子异常" << root->_key << endl;
		}
		return _IsBlance(root->_left) && _IsBlance(root->_right);
	}
	int _Height(Node* root)
	{
		if (root == NULL)
			return 0;
		int right = _Height(root->_right);
		int left = _Height(root->_left);
		if (right > left)
			return (right + 1);
		else
			return (left + 1);
	}
	void _InOrder(Node* root)
	{
		if (root == NULL)
		{
			return;
		}
		else
		{
			_InOrder(root->_left);
			cout << root->_key << " ";
			_InOrder(root->_right);
		}
	}
protected:
	Node* _root;
};

#include "AVLTree.h"
void Test1()
{
	int a[9] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	AVLTree<int, int> avl;
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		avl.Insert(a[i],i);
	}
	avl.InOrder();
	cout<<avl.IsBlance()<<endl;

	AVLTreeNode<int, int>* ret1 = avl.Find(18);
	if (ret1)
		cout << ret1->_key << ":" << ret1->_value << endl;
	else
		cout << "不存在ret1" << endl;

	AVLTreeNode<int, int>* ret2 = avl.Find(1);
	if (ret2)
		cout << ret2->_key << ":" << ret2->_value << endl;
	else
		cout << "不存在ret2" << endl;

	avl.Remove(26);
	avl.Remove(18);
	avl.Remove(15);
	avl.InOrder();

	avl.Remove(3);
	cout << avl.Remove(7) << endl;
	avl.Remove(7);
	avl.Remove(9); 
	avl.Remove(11);
	avl.Remove(14);
	avl.Remove(15);
	cout << avl.Remove(100) << endl;
	avl.Remove(16);
	avl.Remove(18);
	avl.Remove(26);

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

	AVLTreeNode<int, int>* ret1 = avl.Find(5);
	if (ret1)
		cout << ret1->_key << ":" << ret1->_value << endl;
	else
		cout << "不存在ret1" << endl;

	AVLTreeNode<int, int>* ret2 = avl.Find(88);
	if (ret2)
		cout << ret2->_key << ":" << ret2->_value << endl;
	else
		cout << "不存在ret2" << endl;

	avl.Remove(14);
	avl.Remove(16);
	avl.Remove(7);
	avl.InOrder();

	avl.Remove(15);
	avl.Remove(6);
	avl.Remove(5);
	cout << avl.Remove(4) << endl;
	avl.Remove(4);
	avl.Remove(3);
	avl.Remove(2);
	avl.Remove(1);
	cout << avl.Remove(100) << endl;
	avl.Remove(7);
	avl.Remove(16);

	avl.InOrder();
}
int main()
{
	Test1();
	cout << endl;
	cout << endl;
	Test2();
	return 0;
}

实现结果:

时间: 2024-10-14 00:21:49

平衡二叉搜索树的相关文章

平衡二叉搜索树(AVL树)的原理及实现源代码(有图文详解和C++、Java实现代码)

一.AVL树(平衡二叉搜索树)是什么? AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的.AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个非叶子结点的左右子树的高度之差的绝对值(平衡因子)最多为1. 例如: 5             5 / \            /  \ 2   6         2   6 / \    \         / \ 1  4   7       1  4

数据结构(三):非线性逻辑结构-特殊的二叉树结构:堆、哈夫曼树、二叉搜索树、平衡二叉搜索树、红黑树、线索二叉树

在上一篇数据结构的博文<数据结构(三):非线性逻辑结构-二叉树>中已经对二叉树的概念.遍历等基本的概念和操作进行了介绍.本篇博文主要介绍几个特殊的二叉树,堆.哈夫曼树.二叉搜索树.平衡二叉搜索树.红黑树.线索二叉树,它们在解决实际问题中有着非常重要的应用.本文主要从概念和一些基本操作上进行分类和总结. 一.概念总揽 (1) 堆 堆(heap order)是一种特殊的表,如果将它看做是一颗完全二叉树的层次序列,那么它具有如下的性质:每个节点的值都不大于其孩子的值,或每个节点的值都不小于其孩子的值

【算法学习】AVL平衡二叉搜索树原理及各项操作编程实现(C语言)

#include<stdio.h> #include "fatal.h" struct AvlNode; typedef struct AvlNode *Position; typedef struct AvlNode *AvlTree; typedef int ElementType ; AvlTree MakeEmpty(AvlTree T); Position Find(ElementType X,AvlTree T); Position FindMin(AvlTre

平衡二叉搜索树(AVL树,红黑树)数据结构和区别

平衡二叉搜索树(Balanced Binary Search Tree) 经典常见的自平衡的二叉搜索树(Self-balancing Binary Search Tree)有 ① AVL树 :Windows NT 内核中广泛使用 ② 红黑树:C++ STL(比如 map.set )Java 的 TreeMap.TreeSet.HashMap.HashSet  Linux 的进程调度  Ngix 的 timer 管理 1 AVL树  vs  红黑树 ①AVL树 平衡标准比较严格:每个左右子树的高度

平衡二叉搜索树/AVL二叉树 C实现

//AVTree.h 1 #ifndef MY_AVLTREE_H 2 #define MY_AVLTREE_H 3 typedef int ElementType; 4 struct TreeNode 5 { 6 ElementType data; 7 struct TreeNode *left; 8 struct TreeNode *right; 9 int height; 10 }; 11 typedef struct TreeNode TreeNode; 12 typedef TreeN

算法二叉搜索树之AVL树

最近学习了二叉搜索树中的AVL树,特在此写一篇博客小结. 1.引言 对于二叉搜索树而言,其插入查找删除等性能直接和树的高度有关,因此我们发明了平衡二叉搜索树.在计算机科学中,AVL树是最先发明的自平衡二叉搜索树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.对于N个节点的AVL树,由于树高被限制为lgN,因此其插入查找删除操作耗时为O(lgN). 2.旋转 在讲解关键步骤插入与删除以前,首先我们先定义一些辅助用的操作:旋转.旋转分为左旋和右旋,其示意图如下: 相信上

二叉搜索树的局限性

-------------------siwuxie095 二叉搜索树的局限性 二叉搜索树在时间性能上是具有局限性的 同样的数据,可以对应不同的二叉搜索树,如下: 二叉搜索树可能退化成链表,相应的,二叉搜索树的查找操作是和这棵树 的高度相关的,而此时这颗树的高度就是这颗树的节点数 n,同时二叉搜 索树相应的算法全部退化成 O(n) 级别 显然,说二叉搜索树的查找.插入.删除 这三个操作都是 O(lgn) 级别的, 只是一个大概的估算,具体要和二叉搜索树的形状相关 二叉搜索树并不能像堆那样,保证所

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: BST树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中: 如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树 的搜索性能逼近二分查找:但它比连续内存空间的二分查找的优点是,改变BST树结构 插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销: 如:

108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树

将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树.此题中,一个高度平衡二叉树是指一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1.示例:给定有序数组: [-10,-3,0,5,9],一种可行答案是:[0,-3,9,-10,null,5],它可以表示成下面这个高度平衡二叉搜索树:      0     / \   -3   9   /   / -10  5详见:https://leetcode.com/problems/convert-sorted-array-to-binary