AVL 树

17 篇文章 0 订阅
11 篇文章 0 订阅

目录

1.AVL树的概念

2.AVL树的操作(KV模型)

2.1 AVL树的节点定义

2.2 AVL树的查找

2.3 AVL树的插入

2.4 AVL树的删除

3. AVL树整体代码

4. AVL树的性能


1.AVL树的概念

二叉搜索树可以缩短查找的效率,但在某些情况二叉搜索树会发生退化变成单支树,这是查找的效率对下。
AVL树是在二叉搜索树原有的规则下,加以限制:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

一颗具有以下性质的二叉搜索树,是AVL树:
1. 每个节点的左右子树的高度之差(平衡因子)的绝对值不超过-1、0、1
2. 每个节点的左右子树都是AVL树
3. 空树也是AVL树

平衡因子 = 右子树高度 - 左子树高度(也可以是左-右,不影响)

一颗n个节点的AVL树,其高度可保持在\log _{2}n左右,搜索时间复杂度为O(log n)

2.AVL树的操作(KV模型)

2.1 AVL树的节点定义

AVL树的节点可以使用三叉链结构,_parent指向节点的父节点

template <class K, class V>
struct AVLTreeNode
{
	AVLTreeNode(const pair<K, V>& kv)
		:_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr),_bf(0)
	{}
	//三叉链
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;
	pair<K, V> _kv;
	//平衡因子:右 - 左,平衡因子的绝对值   ≤  1
	int _bf;
};

2.2 AVL树的查找

查找的key小于当前节点的key,则向左继续查找
查找的key大于当前节点的key,则向右继续查找
走到nullptr,说明查找的key值不存在

Node* find(const K& key)
{
	Node* cur = _root;
	while (cur)
	{
		if (key > cur->_kv.first)
			cur = cur->_right;
		else if (key < cur->_kv.first)
			cur = cur->_left;
		else
			return cur;
	}
	//key不存在
	return nullptr;
}

2.3 AVL树的插入

AVL树的插入过程:
1. 先查找key值的位置,若key值已存在就结束查找;若key值不存在就找到插入位置并插入。
2. 调整平衡因子:
插入一个节点,会影响部分祖先节点的平衡因子
插入在左子树,平衡因子--
插入在右子树,平衡因子++
是否继续往上更新祖先的平衡因子,需要看parent的子树的高度是否变化:

3. 平衡因子等于2/-2时,需要进行旋转操作,调整数的结构使之平衡:

a. 新节点插入较高左子树左侧--右单旋

旋转之后根节点的平衡因子变为0,不再需要向上更新平衡因子
连接根节点的parent指针时,需要判断根节点是上层节点的左孩子还是右孩子

//右旋
void RotateR(Node* parent)
{
	Node* parent_L = parent->_left;
	Node* parent_L_R = parent_L->_right;

	parent->_left = parent_L_R;
	if(parent_L_R != nullptr)
		parent_L_R->_parent = parent;

	Node* parent_parent = parent->_parent;
	
	parent_L->_right = parent;
	parent->_parent = parent_L;

	//parent_L更新后是根节点
	if (parent_parent == nullptr)
	{
		_root = parent_L;
		parent_L->_parent = nullptr;
	}
	//parent_L 更新后不是根节点,可能属于上层节点的左节点或右节点
	else
	{
		if (parent == parent_parent->_left)
		{
			parent_L->_parent = parent_parent;
			parent_parent->_left = parent_L;
		}
		else
		{
			parent_L->_parent = parent_parent;
			parent_parent->_right = parent_L;
		}
	}
	//更新_bf
	parent->_bf = parent_L->_bf = 0;
}

b. 新节点插入较高右子树右侧--左单旋

旋转之后根节点的平衡因子变为0,不再需要向上更新平衡因子
连接根节点的parent指针时,需要判断根节点是上层节点的左孩子还是右孩子 

//左旋
void RotateL(Node* parent)
{
	Node* parent_R = parent->_right;
	Node* parent_R_L = parent_R->_left;
	
	parent->_right = parent_R_L;
	if (parent_R_L != nullptr)
		parent_R_L->_parent = parent;

	Node* parent_parent = parent->_parent;

	parent_R->_left = parent;
	parent->_parent = parent_R;

	//parent_R更新后是根节点
	if (parent_parent == nullptr)
	{
		_root = parent_R;
		parent_R->_parent = nullptr;
	}
	//parent_R 更新后不是根节点,可能属于上层节点的左节点或右节点
	else
	{
		if (parent == parent_parent->_left)
		{
			parent_R->_parent = parent_parent;
			parent_parent->_left = parent_R;
		}
		else
		{
			parent_R->_parent = parent_parent;
			parent_parent->_right = parent_R;
		}
	}
	parent->_bf = parent_R->_bf = 0;
}

c. 新节点插入较高左子树右侧--左单旋(左子树)+右单旋(整体)

两次旋转后根节点的平衡因子为0
根节点左右子树的平衡因子由插入位置是b和c有关,插入b则根节点右子树平衡因子为1,左子树平衡因子为0;插入c则根节点左子树平衡因子为-1,右子树平衡因子为0。

//左旋+右旋
void RotateLR(Node* parent)
{
	Node* parent_L = parent->_left;
	Node* parent_L_R = parent_L->_right;
	int bf = parent_L_R->_bf;
	RotateL(parent_L);
	RotateR(parent);
	//更新_bf
	if (bf == 0)
	{
		parent->_bf = 0;
		parent_L->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else if (bf == -1)
	{
		parent->_bf = 1;
		parent_L->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else if (bf == 1)
	{
		parent_L->_bf = -1;
		parent->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else//意外处理
	{
		//cout << "bf超过2" << endl;
		assert(false);
	}
}

d. 新节点插入较高右子树左侧--右单旋(右子树)+  左单旋(整体)

两次旋转后根节点的平衡因子为0
根节点左右子树的平衡因子由插入位置是b和c有关,插入b则根节点左子树平衡因子为0,右子树平衡因子为1;插入c则根节点右子树平衡因子为0,左子树平衡因子为-1。

//右旋+左旋
void RotateRL(Node* parent)
{
	Node* parent_R = parent->_right;
	Node* parent_R_L = parent_R->_left;
	int bf = parent_R_L->_bf;
	RotateR(parent_R);
	RotateL(parent);
	//更新_bf
	if (bf == 0)
	{
		parent->_bf = 0;
		parent_R->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else if (bf == 1)
	{
		parent->_bf = -1;
		parent_R->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else if (bf == -1)
	{
		parent_R->_bf = 1;
		parent->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else//意外处理
	{
		cout << "bf超出2" << endl;
		assert(false);
	}
}

insert的整体代码:

bool insert(const pair<K, V>& kv)
{
	//插入一个节点,会影响部分祖先节点的平衡因子
	//插入在左子树,平衡因子--
	//插入在右子树,平衡因子++
	//是否继续往上更新祖先的平衡因子,需要看parent的子树的高度是否变化:
	//1. parent的平衡因子 == 0
	//说明parent的平衡因子更新前是1/-1,插入节点插入矮的一边,parent所在子树高度不变,不需要继续往上更新
	//2. parent的平衡因子 == 1/-1
	// 说明parent的平衡因子更新前是0,插入节点插入任意一边,parent所在子树高度都会变化,需要继续向上更新
	//3. parent的平衡因子 == 2/-2
	//说明parent的平衡因子更新前是1/-1,插入节点插入在高的那边,进一步加剧parent所在的子树的平衡,违反AVL规则,需要旋转处理
	if (_root == nullptr)
	{
		_root = new Node(kv);
		return true;
	}

	Node* cur = _root;
	Node* parent = nullptr;
	//查找
	while (cur)
	{
		if (kv.first > cur->_kv.first)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (kv.second < cur->_kv.first)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
			//key重复
			return false;
	}
	//插入
	cur = new Node(kv);
	if (kv.first > parent->_kv.first)
	{
		parent->_right = cur;
		cur->_parent = parent;
	}
	else
	{
		parent->_left = cur;
		cur->_parent = parent;
	}
	//更新平衡因子_bf
	while (parent)
	{
		//更新_bf
		if (cur == parent->_left)
			parent->_bf--;
		else
			parent->_bf++;
		//没有增高,就不需要向上更新了
		if (parent->_bf == 0)
			break;
		//增高了,需要继续向上更新_bf
		else if (parent->_bf == 1 || parent->_bf == -1)
		{
			cur = parent;
			parent = parent->_parent;
		}
		//增高了,_bf == 2,AVL树不平衡了,需要旋转了
		else if (parent->_bf == 2 || parent->_bf == -2)
		{
			//四种情况
			//右旋
			if (parent->_bf == -2 && cur->_bf == -1)
				RotateR(parent);
			//左旋
			else if (parent->_bf == 2 && cur->_bf == 1)
				RotateL(parent);
			//左旋+右旋
			else if (parent->_bf == -2 && cur->_bf == 1)
				RotateLR(parent);
			//右旋+左旋
			else if (parent->_bf == 2 && cur->_bf == -1)
				RotateRL(parent);
			//旋转后该子树的根的_bf == 0,不需要再向上更新_bf了
			break;
		}
		else//意外处理
		{
			//cout << "平衡因子的绝对值超过2" << endl;
			assert(false);
		}
	}
    return true;
}
//左旋
void RotateL(Node* parent)
{
	Node* parent_R = parent->_right;
	Node* parent_R_L = parent_R->_left;
	
	parent->_right = parent_R_L;
	if (parent_R_L != nullptr)
		parent_R_L->_parent = parent;

	Node* parent_parent = parent->_parent;

	parent_R->_left = parent;
	parent->_parent = parent_R;

	//parent_R更新后是根节点
	if (parent_parent == nullptr)
	{
		_root = parent_R;
		parent_R->_parent = nullptr;
	}
	//parent_R 更新后不是根节点,可能属于上层节点的左节点或右节点
	else
	{
		if (parent == parent_parent->_left)
		{
			parent_R->_parent = parent_parent;
			parent_parent->_left = parent_R;
		}
		else
		{
			parent_R->_parent = parent_parent;
			parent_parent->_right = parent_R;
		}
	}
	parent->_bf = parent_R->_bf = 0;
}
//右旋
void RotateR(Node* parent)
{
	Node* parent_L = parent->_left;
	Node* parent_L_R = parent_L->_right;

	parent->_left = parent_L_R;
	if(parent_L_R != nullptr)
		parent_L_R->_parent = parent;

	Node* parent_parent = parent->_parent;
	
	parent_L->_right = parent;
	parent->_parent = parent_L;

	//parent_L更新后是根节点
	if (parent_parent == nullptr)
	{
		_root = parent_L;
		parent_L->_parent = nullptr;
	}
	//parent_L 更新后不是根节点,可能属于上层节点的左节点或右节点
	else
	{
		if (parent == parent_parent->_left)
		{
			parent_L->_parent = parent_parent;
			parent_parent->_left = parent_L;
		}
		else
		{
			parent_L->_parent = parent_parent;
			parent_parent->_right = parent_L;
		}
	}
	//更新_bf
	parent->_bf = parent_L->_bf = 0;
}
//右旋+左旋
void RotateRL(Node* parent)
{
	Node* parent_R = parent->_right;
	Node* parent_R_L = parent_R->_left;
	int bf = parent_R_L->_bf;
	RotateR(parent_R);
	RotateL(parent);
	//更新_bf
	if (bf == 0)
	{
		parent->_bf = 0;
		parent_R->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else if (bf == 1)
	{
		parent->_bf = -1;
		parent_R->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else if (bf == -1)
	{
		parent_R->_bf = 1;
		parent->_bf = 0;
		parent_R_L->_bf = 0;
	}
	else//意外处理
	{
		cout << "bf超出2" << endl;
		assert(false);
	}
}
//左旋+右旋
void RotateLR(Node* parent)
{
	Node* parent_L = parent->_left;
	Node* parent_L_R = parent_L->_right;
	int bf = parent_L_R->_bf;
	RotateL(parent_L);
	RotateR(parent);
	//更新_bf
	if (bf == 0)
	{
		parent->_bf = 0;
		parent_L->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else if (bf == -1)
	{
		parent->_bf = 1;
		parent_L->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else if (bf == 1)
	{
		parent_L->_bf = -1;
		parent->_bf = 0;
		parent_L_R->_bf = 0;
	}
	else//意外处理
	{
		//cout << "bf超过2" << endl;
		assert(false);
	}
}

2.4 AVL树的删除

在二叉搜索树的篇章介绍了二叉搜索树的删除,分为四种情况,这一步AVL树的删除与二叉搜索树的操作相同,只不过AVL树删除节点后需要更新平衡因子,最差情况需要一直调整到根节点的位置。
AVL树删除操作过程:

1. 根据key值找到需要删除的节点(走到nullptr说明该节点不存在)
2. 删除节点:
a. 删除节点没有孩子节点,直接删除
b. 删除节点只有一个孩子节点,孩子节点替代删除节点的位置,删除节点
c. 删除节点有两个孩子节点,向删除节点的右子树查找key值最小节点,将最小节点的key值覆盖删除节点的key,接着删除最小节点(此时最小节点一定没有孩子节点或只有一个右孩子节点,删除该节点属于a或b情况;最小节点是最左的节点)
3. 调整平衡因子:
删除一个节点,会影响部分祖先节点的平衡因子
删除在左子树,平衡因子++
删除在右子树,平衡因子--
是否继续往上更新祖先的平衡因子,需要看parent的子树的高度是否变化:

旋转处理:
1. 删除节点在较低左子树

2. 删除节点在较低右子树: 

bool erase(const K& key)
{
	if (_root == nullptr)
		return false;
	//查找
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (key > cur->_kv.first)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (key < cur->_kv.first)
		{
			parent = cur;
			cur = cur->_left;
		}
		else  //key == cur->_kv.first
			break;
	}
	//判断cur是否为空,空表示不存在
	if (cur == nullptr)
		return false;
	//key找到了,进行删除,删除有4种情况
	// 
	//删除节点没有孩子节点
	//删除节点只有一个右孩子节点
	if (cur->_left == nullptr)
	{
		//cur是根节点
		if (parent == nullptr)
		{
			_root = cur->_right;
			if(_root != nullptr)
				_root->_parent = nullptr;
			//bf不变
			delete cur;
			return true;
		}
		//不是根节点
		else
		{
			//删除节点是parent的左边
			if (cur == parent->_left)
			{
				parent->_left = cur->_right;
				if (cur->_right != nullptr)
					cur->_right->_parent = parent;
				parent->_bf++;
			}
			//删除节点是parent的右边
			else if (cur == parent->_right)
			{
				parent->_right = cur->_right;
				if (cur->_right != nullptr)
					cur->_right->_parent = parent;
				parent->_bf--;
			}
		}
	}
	//删除节点只有一个左孩子
	else if (cur->_right == nullptr)
	{
		//cur是根节点
		if (parent == nullptr)
		{
			_root = cur->_left;
			if(_root != nullptr)
				_root->_parent = nullptr;
			//bf不变
			delete cur;
			return true;
		}
		//cur不是根节点
		else
		{
			//删除节点是parent的左节点
			if (cur == parent->_left)
			{
				parent->_left = cur->_left;
				if (cur->_left != nullptr)
					cur->_left->_parent = parent;
				parent->_bf++;
			}
			else if (cur == parent->_right)
			{
				parent->_right = cur->_left;
				if (cur->_left != nullptr)
					cur->_left->_parent = parent;
				parent->_bf--;
			}
		}
	}
	//删除节点有两个孩子节点
	else
	{
		Node* minNode = cur->_right;
		Node* minNodeParent = cur;
		while (minNode->_left != nullptr)
		{
			//最左就是最小节点
			minNodeParent = minNode;
			minNode = minNode->_left;
		}
		//覆盖cur的kv
		cur->_kv = minNode->_kv;
		//删除最小节点
		if (minNode == minNodeParent->_left)
		{
			minNodeParent->_left = minNode->_right;
			if (minNode->_right != nullptr)
				minNode->_right->_parent = minNodeParent;
			minNodeParent->_bf++;
			cur = minNode;
			parent = minNodeParent;
		}
		else//注意这个情况--cur就是minNodeParent
		{
			minNodeParent->_right = minNode->_right;
			if (minNode->_right != nullptr)
				minNode->_right->_parent = minNodeParent;
			minNodeParent->_bf--;
			cur = minNode;
			parent = minNodeParent;
		}
	}
	Node* needDelete = cur;

	//更新平衡因子_bf
	//删除一个节点,parent所在子树不一定全部都矮一节
	//第一次不需要改变parent的bf,因为上面删除操作时就改变了parent的bf,第一次只需要判断是否需要向上改变bf或旋转操作
	bool flag_first = false;
	while (parent)
	{
		if(flag_first)
		{
			//更新_bf
			if (cur == parent->_left)
				//减去-1等于+1
				parent->_bf++;
			else
				parent->_bf--;
		}
		flag_first = true;

		//删除后为1/-1,整体最高高度不变,不需要继续向上更新
		if (parent->_bf == 1 || parent->_bf == -1)
			break;
		//删除后为0,说明整体高度变矮了
		else if (parent->_bf == 0)
		{
			cur = parent;
			parent = parent->_parent;
		}
		//_bf == 2,AVL树不平衡了,需要旋转了
		else if (parent->_bf == 2)
		{
			if (parent->_right->_bf == 0)
			{
				Node* p = parent;
				Node* p_r = p->_right;
				RotateL(parent);
				p->_bf = 1;
				p_r->_bf = -1;
				break;
			}
			else if (parent->_right->_bf == 1)
			{
				Node* p = parent;
				Node* p_r = parent->_right;
				RotateL(parent);
				p->_bf = 0;
				p_r->_bf = 0;
				cur = p_r;
				parent = p_r->_parent;
			}
			else//parent->_right->_bf == -1
			{
				Node* p = parent;
				Node* p_r = parent->_right;
				Node* p_r_l = p_r->_left;
				RotateRL(parent);
				p_r_l->_bf = 0;
				p->_bf = _Height(p->_right) - _Height(p->_left);
				p_r->_bf = _Height(p_r->_right) - _Height(p_r->_left);
				cur = p_r_l;
				parent =p_r_l->_parent;
			}
		}
		else if (parent->_bf == -2)
		{
			if (parent->_left->_bf == 0)
			{
				Node* p = parent;
				Node* p_l = parent->_left;
				RotateR(parent);
				p->_bf = -1;
				p_l->_bf = 1;
				break;
			}
			else if (parent->_left->_bf == 1)
			{
				Node* p = parent;
				Node* p_l = parent->_left;
				Node* p_l_r = p_l->_right;
				RotateLR(parent);
				p_l_r->_bf = 0;
				p_l->_bf = _Height(p_l->_right) - _Height(p_l->_left);
				p->_bf = _Height(p->_right) - _Height(p->_left);
				cur = p_l_r;
				parent = p_l_r->_parent;
			}
			else // == -1
			{
				Node* p = parent;
				Node* p_l = parent->_left;
				RotateR(parent);
				p->_bf = 0;
				p_l->_bf = 0;
				cur = p_l;
				parent = p_l->_parent;
			}
		}
		else//意外处理
		{
			//cout << "平衡因子的绝对值超过2" << endl;
			assert(false);
		}
	}
	delete needDelete;
	return true;
}

3. AVL树整体代码

#pragma once
#include <iostream>
#include <time.h>
#include <assert.h>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>
#include <set>
#include <list>
#include <algorithm>
using namespace std;

namespace myAVLTree
{
	template <class K, class V>
	struct AVLTreeNode
	{
		AVLTreeNode(const pair<K, V>& kv)
			:_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr),_bf(0)
		{}
		//三叉链
		AVLTreeNode<K, V>* _left;
		AVLTreeNode<K, V>* _right;
		AVLTreeNode<K, V>* _parent;
		pair<K, V> _kv;
		//平衡因子:右 - 左,平衡因子的绝对值   ≤  1
		int _bf;
	};

	template <class K, class V>
	class AVLTree
	{
		typedef AVLTreeNode<K, V> Node;
	public:
		AVLTree()
			:_root(nullptr)
		{}
		AVLTree(const AVLTree<K,V>& tree)
		{
			_root = _Copy(tree._root, nullptr);
		}
		AVLTree<K, V>& operator=(AVLTree<K, V> tree)
		{
			//利用临时变量出作用域销毁
			swap(_root, tree._root);
			return *this;
		}
		~AVLTree()
		{
			_destroy(_root);
			_root = nullptr;
		}
		bool insert(const pair<K, V>& kv)
		{
			//插入一个节点,会影响部分祖先节点的平衡因子
			//插入在左子树,平衡因子--
			//插入在右子树,平衡因子++
			//是否继续往上更新祖先的平衡因子,需要看parent的子树的高度是否变化:
			//1. parent的平衡因子 == 0
			//说明parent的平衡因子更新前是1/-1,插入节点插入矮的一边,parent所在子树高度不变,不需要继续往上更新
			//2. parent的平衡因子 == 1/-1
			// 说明parent的平衡因子更新前是0,插入节点插入任意一边,parent所在子树高度都会变化,需要继续向上更新
			//3. parent的平衡因子 == 2/-2
			//说明parent的平衡因子更新前是1/-1,插入节点插入在高的那边,进一步加剧parent所在的子树的平衡,违反AVL规则,需要旋转处理
			if (_root == nullptr)
			{
				_root = new Node(kv);
				return true;
			}

			Node* cur = _root;
			Node* parent = nullptr;
			//查找
			while (cur)
			{
				if (kv.first > cur->_kv.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (kv.second < cur->_kv.first)
				{
					parent = cur;
					cur = cur->_left;
				}
				else
					//key重复
					return false;
			}
			//插入
			cur = new Node(kv);
			if (kv.first > parent->_kv.first)
			{
				parent->_right = cur;
				cur->_parent = parent;
			}
			else
			{
				parent->_left = cur;
				cur->_parent = parent;
			}
			//更新平衡因子_bf
			while (parent)
			{
				//更新_bf
				if (cur == parent->_left)
					parent->_bf--;
				else
					parent->_bf++;
				//没有增高,就不需要向上更新了
				if (parent->_bf == 0)
					break;
				//增高了,需要继续向上更新_bf
				else if (parent->_bf == 1 || parent->_bf == -1)
				{
					cur = parent;
					parent = parent->_parent;
				}
				//增高了,_bf == 2,AVL树不平衡了,需要旋转了
				else if (parent->_bf == 2 || parent->_bf == -2)
				{
					//四种情况
					//右旋
					if (parent->_bf == -2 && cur->_bf == -1)
						RotateR(parent);
					//左旋
					else if (parent->_bf == 2 && cur->_bf == 1)
						RotateL(parent);
					//左旋+右旋
					else if (parent->_bf == -2 && cur->_bf == 1)
						RotateLR(parent);
					//右旋+左旋
					else if (parent->_bf == 2 && cur->_bf == -1)
						RotateRL(parent);
					//旋转后该子树的根的_bf == 0,不需要再向上更新_bf了
					break;
				}
				else//意外处理
				{
					//cout << "平衡因子的绝对值超过2" << endl;
					assert(false);
				}
			}
			return true;
		}
		Node* find(const K& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (key > cur->_kv.first)
					cur = cur->_right;
				else if (key < cur->_kv.first)
					cur = cur->_left;
				else
					return cur;
			}
			//key不存在
			return nullptr;
		}
		bool erase(const K& key)
		{
			if (_root == nullptr)
				return false;
			//查找
			Node* cur = _root;
			Node* parent = nullptr;
			while (cur)
			{
				if (key > cur->_kv.first)
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (key < cur->_kv.first)
				{
					parent = cur;
					cur = cur->_left;
				}
				else  //key == cur->_kv.first
					break;
			}
			//判断cur是否为空,空表示不存在
			if (cur == nullptr)
				return false;
			//key找到了,进行删除,删除有4种情况
			// 
			//删除节点没有孩子节点
			//删除节点只有一个右孩子节点
			if (cur->_left == nullptr)
			{
				//cur是根节点
				if (parent == nullptr)
				{
					_root = cur->_right;
					if(_root != nullptr)
						_root->_parent = nullptr;
					//bf不变
					delete cur;
					return true;
				}
				//不是根节点
				else
				{
					//删除节点是parent的左边
					if (cur == parent->_left)
					{
						parent->_left = cur->_right;
						if (cur->_right != nullptr)
							cur->_right->_parent = parent;
						parent->_bf++;
					}
					//删除节点是parent的右边
					else if (cur == parent->_right)
					{
						parent->_right = cur->_right;
						if (cur->_right != nullptr)
							cur->_right->_parent = parent;
						parent->_bf--;
					}
				}
			}
			//删除节点只有一个左孩子
			else if (cur->_right == nullptr)
			{
				//cur是根节点
				if (parent == nullptr)
				{
					_root = cur->_left;
					if(_root != nullptr)
						_root->_parent = nullptr;
					//bf不变
					delete cur;
					return true;
				}
				//cur不是根节点
				else
				{
					//删除节点是parent的左节点
					if (cur == parent->_left)
					{
						parent->_left = cur->_left;
						if (cur->_left != nullptr)
							cur->_left->_parent = parent;
						parent->_bf++;
					}
					else if (cur == parent->_right)
					{
						parent->_right = cur->_left;
						if (cur->_left != nullptr)
							cur->_left->_parent = parent;
						parent->_bf--;
					}
				}
			}
			//删除节点有两个孩子节点
			else
			{
				Node* minNode = cur->_right;
				Node* minNodeParent = cur;
				while (minNode->_left != nullptr)
				{
					//最左就是最小节点
					minNodeParent = minNode;
					minNode = minNode->_left;
				}
				//覆盖cur的kv
				cur->_kv = minNode->_kv;
				//删除最小节点
				if (minNode == minNodeParent->_left)
				{
					minNodeParent->_left = minNode->_right;
					if (minNode->_right != nullptr)
						minNode->_right->_parent = minNodeParent;
					minNodeParent->_bf++;
					cur = minNode;
					parent = minNodeParent;
				}
				else//注意这个情况--cur就是minNodeParent
				{
					minNodeParent->_right = minNode->_right;
					if (minNode->_right != nullptr)
						minNode->_right->_parent = minNodeParent;
					minNodeParent->_bf--;
					cur = minNode;
					parent = minNodeParent;
				}
			}
			Node* needDelete = cur;

			//更新平衡因子_bf
			//删除一个节点,parent所在子树不一定全部都矮一节
			//第一次不需要改变parent的bf,因为上面删除操作时就改变了parent的bf,第一次只需要判断是否需要向上改变bf或旋转操作
			bool flag_first = false;
			while (parent)
			{
				if(flag_first)
				{
					//更新_bf
					if (cur == parent->_left)
						//减去-1等于+1
						parent->_bf++;
					else
						parent->_bf--;
				}
				flag_first = true;

				//删除后为1/-1,整体最高高度不变,不需要继续向上更新
				if (parent->_bf == 1 || parent->_bf == -1)
					break;
				//删除后为0,说明整体高度变矮了
				else if (parent->_bf == 0)
				{
					cur = parent;
					parent = parent->_parent;
				}
				//_bf == 2,AVL树不平衡了,需要旋转了
				else if (parent->_bf == 2)
				{
					if (parent->_right->_bf == 0)
					{
						Node* p = parent;
						Node* p_r = p->_right;
						RotateL(parent);
						p->_bf = 1;
						p_r->_bf = -1;
						break;
					}
					else if (parent->_right->_bf == 1)
					{
						Node* p = parent;
						Node* p_r = parent->_right;
						RotateL(parent);
						p->_bf = 0;
						p_r->_bf = 0;
						cur = p_r;
						parent = p_r->_parent;
					}
					else//parent->_right->_bf == -1
					{
						Node* p = parent;
						Node* p_r = parent->_right;
						Node* p_r_l = p_r->_left;
						RotateRL(parent);
						p_r_l->_bf = 0;
						p->_bf = _Height(p->_right) - _Height(p->_left);
						p_r->_bf = _Height(p_r->_right) - _Height(p_r->_left);
						cur = p_r_l;
						parent =p_r_l->_parent;
					}
				}
				else if (parent->_bf == -2)
				{
					if (parent->_left->_bf == 0)
					{
						Node* p = parent;
						Node* p_l = parent->_left;
						RotateR(parent);
						p->_bf = -1;
						p_l->_bf = 1;
						break;
					}
					else if (parent->_left->_bf == 1)
					{
						Node* p = parent;
						Node* p_l = parent->_left;
						Node* p_l_r = p_l->_right;
						RotateLR(parent);
						p_l_r->_bf = 0;
						p_l->_bf = _Height(p_l->_right) - _Height(p_l->_left);
						p->_bf = _Height(p->_right) - _Height(p->_left);
						cur = p_l_r;
						parent = p_l_r->_parent;
					}
					else // == -1
					{
						Node* p = parent;
						Node* p_l = parent->_left;
						RotateR(parent);
						p->_bf = 0;
						p_l->_bf = 0;
						cur = p_l;
						parent = p_l->_parent;
					}
				}
				else//意外处理
				{
					//cout << "平衡因子的绝对值超过2" << endl;
					assert(false);
				}
			}
			delete needDelete;
			return true;
		}
		void InOrder()
		{
			_InOrder(_root);
		}
		bool IsAVLTree()
		{
			return _IsAVLTree(_root);
		}
		
	private:
		void _InOrder(Node* root)
		{
			if (root == nullptr)
				return;
			_InOrder(root->_left);
			//cout << root->_kv.first << ':' << root->_kv.second << " bf:" << root->_bf << endl;
			cout << root->_kv.first << ':' << root->_kv.second  << endl;
			_InOrder(root->_right);
		}
		//计算高度
		int _Height(Node* root)
		{
			if (root == nullptr)
				return 0;
			int leftHeight = _Height(root->_left);
			int rightHeight = _Height(root->_right);

			return max(leftHeight,rightHeight) + 1;
		}
		//判断AVL树的子函数
		bool _IsAVLTree(Node* root)
		{
			if (root == nullptr)
				return true;
			int leftHeight = _Height(root->_left);
			int rightHeight = _Height(root->_right);
			//右 - 左
			int diff = rightHeight - leftHeight;
			//判断高度
			if (diff != root->_bf || diff > 1 || diff < -1)
				return false;
			//if (diff != root->_bf)
			//{
			//	cout << "diff 与 bf不匹配" << endl;
			//	return false;
			//}
			//if (diff > 1 || diff < -1)
			//{
			//	cout << "bf绝对值超过1" << endl;
			//	return false;
			//}

			return _IsAVLTree(root->_left) && _IsAVLTree(root->_right);
		}
		//左旋
		void RotateL(Node* parent)
		{
			Node* parent_R = parent->_right;
			Node* parent_R_L = parent_R->_left;
			
			parent->_right = parent_R_L;
			if (parent_R_L != nullptr)
				parent_R_L->_parent = parent;

			Node* parent_parent = parent->_parent;

			parent_R->_left = parent;
			parent->_parent = parent_R;

			//parent_R更新后是根节点
			if (parent_parent == nullptr)
			{
				_root = parent_R;
				parent_R->_parent = nullptr;
			}
			//parent_R 更新后不是根节点,可能属于上层节点的左节点或右节点
			else
			{
				if (parent == parent_parent->_left)
				{
					parent_R->_parent = parent_parent;
					parent_parent->_left = parent_R;
				}
				else
				{
					parent_R->_parent = parent_parent;
					parent_parent->_right = parent_R;
				}
			}
			parent->_bf = parent_R->_bf = 0;
		}
		//右旋
		void RotateR(Node* parent)
		{
			Node* parent_L = parent->_left;
			Node* parent_L_R = parent_L->_right;

			parent->_left = parent_L_R;
			if(parent_L_R != nullptr)
				parent_L_R->_parent = parent;

			Node* parent_parent = parent->_parent;
			
			parent_L->_right = parent;
			parent->_parent = parent_L;

			//parent_L更新后是根节点
			if (parent_parent == nullptr)
			{
				_root = parent_L;
				parent_L->_parent = nullptr;
			}
			//parent_L 更新后不是根节点,可能属于上层节点的左节点或右节点
			else
			{
				if (parent == parent_parent->_left)
				{
					parent_L->_parent = parent_parent;
					parent_parent->_left = parent_L;
				}
				else
				{
					parent_L->_parent = parent_parent;
					parent_parent->_right = parent_L;
				}
			}
			//更新_bf
			parent->_bf = parent_L->_bf = 0;
		}
		//右旋+左旋
		void RotateRL(Node* parent)
		{
			Node* parent_R = parent->_right;
			Node* parent_R_L = parent_R->_left;
			int bf = parent_R_L->_bf;
			RotateR(parent_R);
			RotateL(parent);
			//更新_bf
			if (bf == 0)
			{
				parent->_bf = 0;
				parent_R->_bf = 0;
				parent_R_L->_bf = 0;
			}
			else if (bf == 1)
			{
				parent->_bf = -1;
				parent_R->_bf = 0;
				parent_R_L->_bf = 0;
			}
			else if (bf == -1)
			{
				parent_R->_bf = 1;
				parent->_bf = 0;
				parent_R_L->_bf = 0;
			}
			else//意外处理
			{
				cout << "bf超出2" << endl;
				assert(false);
			}
		}
		//左旋+右旋
		void RotateLR(Node* parent)
		{
			Node* parent_L = parent->_left;
			Node* parent_L_R = parent_L->_right;
			int bf = parent_L_R->_bf;
			RotateL(parent_L);
			RotateR(parent);
			//更新_bf
			if (bf == 0)
			{
				parent->_bf = 0;
				parent_L->_bf = 0;
				parent_L_R->_bf = 0;
			}
			else if (bf == -1)
			{
				parent->_bf = 1;
				parent_L->_bf = 0;
				parent_L_R->_bf = 0;
			}
			else if (bf == 1)
			{
				parent_L->_bf = -1;
				parent->_bf = 0;
				parent_L_R->_bf = 0;
			}
			else//意外处理
			{
				//cout << "bf超过2" << endl;
				assert(false);
			}
		}
		void _destroy(Node* _root)
		{
			if (_root == nullptr)
				return;
			_destroy(_root->_left);
			_destroy(_root->_right);
			delete _root;
		}
		Node* _Copy(Node* root, Node* newRootParent)
		{
			if (root == nullptr)
				return nullptr;
			Node* newRoot = new Node(root->_kv);
			newRoot->_left = _Copy(root->_left, newRoot);
			newRoot->_right = _Copy(root->_right, newRoot);
			newRoot->_bf = root->_bf;
			newRoot->_parent = newRootParent;

			return newRoot;
		}

	private:
		Node* _root;
	};
}

4. AVL树的性能

AVL树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过1,这
样可以保证查询时高效的时间复杂度,即O(\log _{2}N)。但是如果要对AVL树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(即不会改变),可以考虑AVL树,但一个结构经常修改,就不太适合。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饼干烧饼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值