1、搜索二叉树可能会出现一边树很长另一边树很短的极端情况,这样的话二叉树就会退化,这时我们就引出了AVL树这样的改良版。AVL树会控制两端树的高度差的绝对值小于1。(一般为右数高度减左树高度)

2、AVL树会通过平衡因子来控制,因为是右-左,所以插入左边平衡因子--,右边则++

3、基本结构:

AVL树_头结点

其中_parent是用来找上一节点进行链接

控制AVL的行为:

AVL树_搜索二叉树_02

其中除了插入函数其余函数与搜索二叉树相似。

4、插入函数:

bool Insert(const pair<K, V>& kv)
{
//若头结点为空则直接加
	if (_root == nullptr)
	{
		_root = new Node(kv);
		return true;
	}

	Node* parent = nullptr;
	Node* cur = _root;
	//kv.first相当于BST中的k
  //比较找插入的位置
	while (cur)
	{
		if (cur->_kv.first < kv.first)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_kv.first > kv.first)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			return false;
		}
	}
//找到插入的父节点
	cur = new Node(kv);
	if (parent->_kv.first < kv.first)
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}
  //插入链接
	cur->_parent = parent;

	// 更新平衡因子
	while (parent)
	{
  //左--,右++
		if (cur == parent->_left)
			parent->_bf--;
		else
			parent->_bf++;
//根据parent的平衡因子来判断是否向上更新
//为0结束
		if (parent->_bf == 0)
		{
			break;
		}
    //为1/-1
		else if (parent->_bf == 1 || parent->_bf == -1)
		{
			// 继续往上更新
			cur = parent;
			parent = parent->_parent;
		}
    //为2/-2,违背规则旋转处理
		else if (parent->_bf == 2 || parent->_bf == -2)
		{
			// 不平衡了,旋转处理
			if (parent->_bf == 2 && cur->_bf == 1)
			{
      //左单旋
				RotateL(parent);
			}
			else if (parent->_bf == -2 && cur->_bf == -1)
			{
      //右单旋
				RotateR(parent);
			}
			else if (parent->_bf == 2 && cur->_bf == -1)
			{
      //先右后左
				RotateRL(parent);
			}
			else
			{
      //先左后右
				RotateLR(parent);
			}

			break;
		}
		//若出错则报错
		else
		{
			assert(false);
		}
	}

	return true;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.

左单旋:

AVL树_头结点_03

这里子树的高度为h,h分为0和>=1

h==1:

AVL树_父节点_04

h>=1

AVL树_头结点_05

转完后,改变parent节点,若subRL为空则不链接parent,不为空则链接

还有parent的parent为空则:

AVL树_搜索二叉树_06

若不为空,parent在其父节点的左则向左链接,右同理:

AVL树_头结点_07

更新平衡因子:

AVL树_头结点_08

右单旋:

AVL树_搜索二叉树_09

与左单旋相似:

AVL树_搜索二叉树_10

AVL树_头结点_11

平衡因子的更新:

AVL树_父节点_12

AVL树_头结点_13