[Estructura de datos] Inserción y verificación del árbol AVL

1. Conceptos básicos

1. Antecedentes del desarrollo

  • Los árboles de búsqueda binarios ordinarios degenerarán en una forma similar a una lista enlazada en casos extremos, reduciendo así la eficiencia de la búsqueda a O(N) .

  • Sobre esta base, el matemático soviético e israelí ADelson- VElskii y el matemático soviético LAndis inventaron el árbol AVL o árbol binario equilibrado de búsqueda.

Insertar descripción de la imagen aquí
Insertar descripción de la imagen aquí

Nota: La primera imagen es Adelson-Velskii (1922-2014), la segunda imagen es Landis (1921-1997).

2. Naturaleza

  • El valor absoluto de la diferencia de altura entre los subárboles izquierdo y derecho no es mayor que 1
  • Cada subárbol es un árbol AVL.

Nota: El propósito de esto es controlar estrictamente el equilibrio para mejorar la eficiencia de la búsqueda, pero es imposible controlar la diferencia de altura para que siempre sea 0. En cuanto a por qué no se puede controlar a 0, suponiendo que debe haber una diferencia de altura de 1 entre sólo dos nodos.

2. Principio de implementación

①Insertar operación

1. Factor de equilibrio

Nombre en inglés: factor de equilibrio

  • Objetivo:保证左右子树的高度差的绝对值不大于1
  • La mayoría de las implementaciones:存放的是右子树与左子树的高度差

1.1 Actualización del factor de equilibrio

1.1.1 Cambios de altura de los árboles

① Agregue un nuevo nodo a la izquierda
Insertar descripción de la imagen aquí

② Agregue un nuevo nodo a la derecha

Insertar descripción de la imagen aquí

  • Resumir
  1. Recién agregado a la izquierda, el factor de equilibrio del nodo raíz se reduce en 1
  2. Recién agregado a la derecha, el factor de equilibrio del nodo raíz aumenta en 1
  3. El factor de equilibrio cambia de 0 a 1 o -1

Continuar el análisis:
 dos situaciones de árboles 高度增加1, es decir 平衡因子从0变为1或者-1, dado que la altura cambia, puede provocar que la parte superior del árbol se desequilibre.
como:
Insertar descripción de la imagen aquí

En este momento, debemos actualizar el factor de equilibrio hacia arriba y luego decidir si sumar 1 o restar 1 al factor de equilibrio de la raíz en función del cambio de altura a la derecha y la altura a la izquierda.

  • inferencia:由于可能会向上更新平衡因子,那么AVL树是三叉链的结构。

Como se muestra en la imagen:
Insertar descripción de la imagen aquí

1.1.2 La altura del árbol permanece sin cambios.

① Agregue un nuevo nodo a la izquierda

Insertar descripción de la imagen aquí
② Agregue un nuevo nodo a la derecha

Insertar descripción de la imagen aquí

  • Misma razón
  1. Recién agregado a la izquierda, el factor de equilibrio del nodo raíz se reduce en 1
  2. Recién agregado a la derecha, el factor de equilibrio del nodo raíz aumenta en 1
  3. El factor de equilibrio cambia de 1 o -1 a 0

Continuando con el análisis, la altura del árbol donde se encuentra el nodo raíz es——左右子树高度的最大值 + 1(根节点的高度)

Si el valor máximo de la altura de los subárboles izquierdo y derecho permanece sin cambios, es decir, la altura del árbol permanece sin cambios, es decir, 不用往上继续更新se alcanza el equilibrio.

2. Girar

  • Explicación: Rotar significa dejar 不平衡的树再次平衡的手段.

  • Condición: El factor de equilibrio es 2 o -2, es decir, el valor absoluto de la diferencia de altura es 2.

  • Suplemento: si el factor de equilibrio es mayor o igual a 3, significa que el árbol actual no es un árbol AVL y es necesario verificar el código anterior.

Pero tenemos que clasificar las situaciones nuevamente , porque diferentes situaciones requieren diferentes formas de rotar el árbol para equilibrarlo nuevamente.

2.1Zurdo

  • Explicación: Es decir, la altura del lado derecho es alta y es necesario girarla para bajar la altura del lado derecho para lograr el equilibrio.

Analicémoslo paso a paso, empezando por el más sencillo:

Insertar descripción de la imagen aquí
En este momento, todos los factores de equilibrio se vuelven 0 después de la rotación y el árbol actual alcanza el equilibrio. 注意此时3结点的左结点为空!(detalle)

Pongamos otro ejemplo:

Insertar descripción de la imagen aquí

En este momento, los factores de equilibrio de los factores de equilibrio 1 y 3 se vuelven 0 después de la rotación y el árbol actual alcanza el equilibrio 不用管其它子树的,因为子树必然是AVL树,要不然更不到根节点就停止了.

Finalmente, tomemos un ejemplo un poco más complicado:
Insertar descripción de la imagen aquí
en este momento, el factor de equilibrio de -5 y 0 se convierte en 0 después de la rotación y el árbol actual está equilibrado.

Esta es una imagen concreta para facilitar la comprensión, y luego dibujamos una imagen abstracta de todas las situaciones:
Insertar descripción de la imagen aquí

  • Resumir
  1. 只能Insertar un nodo en la parte c puede provocar 根节点una rotación hacia la izquierda, es decir parent的右边为cur且新增结点在cur的右边.
  2. Después de la rotación cur与parent的平衡因子变为0.
  • detalle
  1. Cuando el nodo padre de b está conectado al padre, es necesario determinar si la parte b está vacía.
  2. Cuando el nodo padre de padre está conectado a cur, es necesario guardar el nodo padre de padre.
  3. Determine si el nodo raíz necesita modificarse en función del nodo principal. Si está vacío, modifíquelo. Si no está vacío, vincule cur al nodo principal del padre y actualice el apuntamiento del nodo padre.
  • implementar código
	void RotateL(Node* parent)
	{
    
    
		//画图分析:
		//操作的结点有cur,cur_left,ppnode
		Node* cur = parent->_right;
		Node* cur_left = cur->_left;
		//将parent的右节点改为cur_left
		parent->_right = cur_left;
		//改变cur_left父节点的转向
		//cur_left可能为空
		if (cur_left != nullptr)
		{
    
    
			cur_left->_parent = parent;
		}
		//将parent链接在cur的左边
		//为了更新cur的parent需要保存parent的父节点
		Node* ppnode = parent->_parent;

		cur->_left = parent;
		parent->_parent = cur;

		//ppnode可能为空
		if (ppnode == nullptr)
		{
    
    
			//需要修改根节点
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
    
    
			//改变ppnode的指向
			if (ppnode->_left == parent)
			{
    
    
				ppnode->_left = cur;
			}
			else
			{
    
    
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;

		}

		//更新平衡因子
		cur->_bf = parent->_bf = 0;

	}

2.2 Rotación a la derecha

Explicación: Es decir, la altura en el lado izquierdo es alta y es necesario girarla para reducir la altura en el lado derecho para lograr el equilibrio.

Se analiza de la misma forma que la rotación hacia la izquierda.

Primero tengamos un sentimiento simple:

Insertar descripción de la imagen aquí

En este momento, los factores de equilibrio de padre y cur se vuelven 0 después de la rotación y el árbol actual alcanza el equilibrio.

Otro ejemplo:
Insertar descripción de la imagen aquí
Finalmente, tomemos un ejemplo un poco más complicado:
Insertar descripción de la imagen aquí

Dibuja diagramas abstractos de todas las situaciones:

Insertar descripción de la imagen aquí

  • Resumir
  1. 只能Insertar un nodo en la parte a puede causar 根节点monorotación hacia la derecha, es decirparent与cur与高度变化的c树的根节点在同一个方向且在parent的左
  2. Después de la rotación cur与parent的平衡因子变为0.

  • Detalles - Igual que la rotación a la izquierda
  1. Cuando el nodo padre de b está conectado al padre, es necesario determinar si la parte b está vacía.
  2. Cuando el nodo padre de padre está conectado a cur, es necesario guardar el nodo padre de padre.
  3. Determine si el nodo raíz necesita modificarse en función del nodo principal. Si está vacío, modifíquelo. Si no está vacío, vincule cur al nodo principal del padre y actualice el apuntamiento del nodo padre.
  • Código de implementación:
		void RotateR(Node* parent)
		{
    
    
			//操作的结点
			Node* cur = parent->_left;
			Node* cur_right = cur->_right;

			//第一步:将cur_right链接到parent的left
			parent->_left = cur_right;
			//更改cur_right的父节点
			//注意:cur_right可能为空
			if (cur_right != nullptr)
			{
    
    
				cur_right->_parent = parent;
			}
			//第二步:将parent链接到cur的右结点。
			//先保存一下parent的父节点
			Node* ppnode = parent->_parent;

			cur->_right = parent;
			parent->_parent = cur;
			//ppnode为空说明需要修改根节点
			if (ppnode == nullptr)
			{
    
    
				_root = cur;
				cur->_parent = nullptr;
			}
			else
			{
    
    
				if (ppnode->_left == parent)
				{
    
    
					ppnode->_left = cur;
				}
				else
				{
    
    
					ppnode->_right = cur;
				}

				cur->_parent = ppnode;
			}
			
			//更新平衡因子
			cur->_bf = parent->_bf = 0;

		}

2.3 Rotación gemela derecha e izquierda

  • Puede entenderse simplemente como una rotación hacia la izquierda que debe procesarse.

Nota: La rotación única no puede resolver el problema porque es 发生了拐弯necesario utilizarla 右旋讲折线变为直线,再进行左旋.

Debido a que hay muchas situaciones, hagamos un diagrama abstracto simple y directo para que la conclusión sea más fácil de entender.

Primero hagamos uno simple:
Insertar descripción de la imagen aquí
primero gire hacia la derecha, luego la polilínea se convierte en una línea recta, luego se convierte en una forma para zurdos y luego gira hacia la izquierda. Finalmente, el factor de equilibrio de cur, cur_left y parent se convierte en 0, y finalmente cur_left se convierte en el nodo raíz.

Imagen re-abstracta:

estado inicial
Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí
Sigue siendo lo mismo, pero hay dos situaciones para discutir:

  1. Agregar un nuevo nodo al árbol c hará que el factor de equilibrio del padre se convierta en -1 y el factor de equilibrio de cur se convierta en 0.
  2. Agregar un nuevo nodo al árbol b hará que el factor de equilibrio del padre se convierta en 0 y el factor de equilibrio de cur se convierta en 1.
  3. No importa en quién esté el nuevo nodo, el factor de equilibrio de cur_left es 0.
  • Mirando el análisis del gráfico, de hecho, independientemente de en quién esté el nuevo nodo, los resultados de las dos rotaciones finales son los mismos, entonces en realidad solo necesitamos dibujar el gráfico sin mirar el nuevo nodo y luego agregar el nuevo nodo basado en el resultado final. Hacer clic en él lo hará más intuitivo.

  • Resumir

  1. Agregar un nuevo nodo al árbol c hará que el factor de equilibrio del padre se convierta en -1 y el factor de equilibrio de cur se convierta en 0.
  2. Agregar un nuevo nodo al árbol b hará que el factor de equilibrio del padre se convierta en 0 y el factor de equilibrio de cur se convierta en 1.
  3. Cur_left es un nodo nuevo y los nodos padre y cur son todos 0.
  • Código de implementación:
	void RotateRL(Node* parent)
	{
    
    
		Node* cur = parent->_right;
		Node* cur_left = cur->_left;

		//CL——CurLeft
		int CL_bf = cur_left->_bf;
		RotateR(cur);
		RotateL(parent);
		//更新平衡因子
		if (CL_bf == 0)
		{
    
    
			cur->_bf = parent->_bf = cur_left->_bf = 0;
			//虽然没必要,但是起到了解耦的作用。
		}
		else if (CL_bf == 1)
		{
    
    
			parent->_bf = -1;
			cur->_bf = cur_left->_bf = 0;
		}
		else if(CL_bf == -1)
		{
    
    
			cur->_bf = 1;
			parent->_bf = cur_left->_bf = 0;
		}
		else
		{
    
    
			cout << __LINE__ << ":" << endl;
			perror("平衡因子有误");
			exit(-1);
		}
	}

2.4 Doble rotación izquierda y derecha

  • Se puede entender que es necesario procesar la rotación a la derecha.

Explicación: La rotación única no puede resolver el problema porque hay un giro. Debe usar la rotación hacia la izquierda para cambiar la polilínea a una línea recta y luego realizar la rotación hacia la derecha.

El método de análisis es el mismo que el de la doble rotación derecha-izquierda.

Comencemos con uno simple:

Insertar descripción de la imagen aquí
Después de girar por primera vez a la izquierda, la polilínea se convierte en una línea recta, adopta una forma hacia la derecha y luego gira a la derecha. El factor de equilibrio final entre cur, cur_left y parent se convierte en 0, y finalmente cur_left se convierte en el nodo raíz.

Hagamos otro resumen:
Insertar descripción de la imagen aquí
sigue siendo lo mismo, pero lo discutiremos en dos situaciones:

  1. Agregar un nuevo nodo al árbol c hará que el factor de equilibrio de cur se convierta en -1 y el factor de equilibrio del padre se convierta en 0.
  2. Agregar un nuevo nodo al árbol b hará que el factor de equilibrio de cur se convierta en 0 y el factor de equilibrio de parent se convierta en 1.
  3. No importa en quién esté el nuevo nodo, el factor de equilibrio de cur_right es 0.

  • Resumir
  1. El factor de equilibrio cur_right es 1, lo que significa que el nuevo nodo está en el árbol b, lo que hará que el factor de equilibrio de cur se convierta en 0 y el factor de equilibrio del padre se convierta en 1.
  2. El factor de equilibrio de cur_right es -1. Agregar un nuevo nodo al árbol c hará que el factor de equilibrio de cur se convierta en -1 y el factor de equilibrio del padre en 0.
  3. El factor de equilibrio de cur_right es 0, y los factores de equilibrio de cur y parent se vuelven 0.
  4. No importa en quién esté el nuevo nodo, el factor de equilibrio de cur_right es 0.
  • Código
		void RotateLR(Node* parent)
		{
    
    
			Node* cur = parent->_left;
			Node* cur_right = cur->_right;
			int CR_bf = cur_right->_bf;

			RotateL(cur);
			RotateR(parent);

			if (CR_bf == 0)
			{
    
    
				parent->_bf = cur->_bf = cur_right->_bf = 0;
			}
			else if(CR_bf == 1)
			{
    
    
				cur->_bf = -1;
				parent->_bf = cur_right->_bf = 0;
			}
			else if (CR_bf == -1)
			{
    
    
				parent->_bf = 1;
				cur->_bf = cur_right->_bf = 0;
			}
			else
			{
    
    
				cout << __LINE__ << ":" << endl;
				perror("平衡因子有误");
				exit(-1);
			}
		} 

②Verificación

ilustrar:

  1. Verifique la diferencia de altura de cada subárbol según la definición.
  2. Es necesario determinar si la diferencia de altura del subárbol derecho actual es igual al factor de equilibrio

Juzgar directamente en función del factor de equilibrio parece un poco autoinfligido. ¿Puedes garantizar que el factor de equilibrio que actualizaste sea correcto? Ni siquiera puedo garantizarlo.

1. Encuentra la altura de un árbol binario.

  • recorrido posterior al pedido
	size_t Height(Node* root)
	{
    
    
		if (root == nullptr)
		{
    
    
			return 0;
		}

		int LHeight = Height(root->_left);
		int RHeight = Height(root->_right);


		return max(LHeight, RHeight) + 1;
	}

2. Determinar si es un árbol AVL.

	bool _IsAVLTree(Node* root)
	{
    
    
		if (root == nullptr)
		{
    
    
			return true;
		}
		int RHeight = Height(root->_right);
		int LHeight = Height(root->_left);

		if (abs(RHeight - LHeight) > 1 || root->_bf != RHeight - LHeight)
		{
    
    
			return false;
		}

		return _IsAVLTree(root->_left) && _IsAVLTree(root->_right);
	}

Optimízalo:

	bool IsAVLTree()
	{
    
    
		bool is_AVL = true;
		_IsAVLTree(_root, is_AVL);

		return is_AVL;
	}

	int _IsAVLTree(Node* root,bool& is_AVL)
	{
    
    
		if (root == nullptr)
		{
    
    
			return 0;
		}
		int RHeight = _IsAVLTree(root->_right, is_AVL);
		int LHeight = _IsAVLTree(root->_left, is_AVL);

		if (abs(RHeight - LHeight) > 1 || root->_bf != RHeight - LHeight)
		{
    
    
			is_AVL = false;
		}
		return max(RHeight, LHeight) + 1;
	}

Código fuente

#include<iostream>
#include<assert.h>
using namespace std;
namespace MY_STL
{
    
    
	template<class Key,class Val>
	struct  AVLTreeNode
	{
    
    
		typedef AVLTreeNode<Key, Val> Node;
		AVLTreeNode(const pair<Key,Val>& key = pair<Key,Val>())
			:_key(key.first)
			,_val(key.second)
			,_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_bf(0)
		{
    
    }

		Key _key;
		Val _val;
		//三叉链的结构
		Node* _left;
		Node* _right;
		Node* _parent;
		int _bf;
	};
	template<class Key, class Val>
	class AVLTree
	{
    
    
		typedef AVLTreeNode<Key, Val> Node;
	public:
		AVLTree()
		{
    
    }

		bool insert(const pair<Key,Val>& val)
		{
    
    
			//第一步:插入操作
			//如果根节点为空
			if (_root == nullptr)
			{
    
    
				_root = new Node(val);
				return true;
			}
			else
			{
    
    
				Node* cur = _root,*parent = _root;
				while (cur)
				{
    
    
					if (cur->_key > val.first)
					{
    
    
						parent = cur;
						cur = cur->_left;

					}
					else if(cur->_key < val.first)
					{
    
    
						parent = cur;
						cur = cur->_right;

					}
					else
					{
    
    
						return false;
					}
				}
				cur = new Node(val);
				if (parent->_key > val.first)
				{
    
    
					parent->_left = cur;
				}
				else
				{
    
    
					parent->_right = cur;
				}
				//更新新增结点的_parent
				cur->_parent = parent;

				//第二步:更新平衡因子
				//平衡因子:
				//1. 定义为右子树的高度减去左子树的高度
				//2. 合法范围为{-1,0,1}
				//3. 新增结点在左,父节点的平衡因子减1
				//4. 新增结点在右,父节点的平衡因子加1
				//5. 当父节点的平衡因子变为0——由-1变0或者1变0时,此时AVL树的高度不变
				//6. 当父节点的平衡因子变为1或者-1,AVL子树的高度变化,继续向上变化。
				//7. 当父节点的平衡因子变为2或者-2时,此时需要旋转,进行平衡
				//8. 当父节点为根节点时,此时需要结束循环。

				while (cur != _root)
				{
    
    
					//更新平衡因子
					if (parent->_left == cur)
					{
    
    
						//左减1
						(parent->_bf)--;
					}
					else
					{
    
    
						//右加1
						(parent->_bf)++;
					}
					//判断平衡因子
					if (parent->_bf == 0)
					{
    
    
						break;
					}
					else if (parent->_bf == 1 || parent->_bf == -1)
					{
    
    
						cur = parent;
						parent = cur->_parent;
					}
					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 if (parent->_bf == -2 && cur->_bf == 1)
						//{
    
    
						//	RotateLR(parent);
						//}
						if (parent->_bf == 2)
						{
    
    
							//左单旋
							if (cur->_bf == 1)
							{
    
    
								RotateL(parent);
							}
							else
							{
    
    
								RotateRL(parent);
							}
						}
						else
						{
    
    
							//右单旋
							if (cur->_bf == -1)
							{
    
    
								RotateR(parent);
							}
							else
							{
    
    
								RotateLR(parent);
							}
						}
						
						//旋转完成,树达到平衡
						break;
					}
				}
				

				return true;
			}
		}
		//根据定义进行判断
		bool IsAVLTree()
		{
    
    
			bool is_AVL = true;
			_IsAVLTree(_root, is_AVL);

			return is_AVL;

			//return _IsAVLTree(_root);
		}

		void Print()
		{
    
    
			_InOrder(_root);
			cout << endl;
		}
		//根据平衡因子进行判断
		//bool IsAVLTree()
		//{
    
    
		//	return _IsAVLTree(_root);
		//}

	private:
		void _InOrder(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return;
			}
			_InOrder(root->_left);
			cout << root->_key << " ";
			_InOrder(root->_right);
		}
		//bool _IsAVLTree(Node* root)
		//{
    
    
		//	if (root == nullptr)
		//		return true;
		//	if (root->_bf >= 2 || root->_bf <= -2)
		//	{
    
    
		//		return false;
		//	}
		//	else
		//	{
    
    
		//		return _IsAVLTree(root->_left) && _IsAVLTree(root->_right);
		//	}
		//}

		//bool IsAVLTree()
		//{
    
    
		//	bool is_AVL = true;
		//	_IsAVLTree(_root, is_AVL);

		//	return is_AVL;
		//}

		size_t Height(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return 0;
			}

			int LHeight = Height(root->_left);
			int RHeight = Height(root->_right);


			return max(LHeight, RHeight) + 1;
		}
		int _IsAVLTree(Node* root,bool& is_AVL)
		{
    
    
			if (root == nullptr)
			{
    
    
				return 0;
			}
			int RHeight = _IsAVLTree(root->_right, is_AVL);
			int LHeight = _IsAVLTree(root->_left, is_AVL);

			if (abs(RHeight - LHeight) > 1 || root->_bf != RHeight - LHeight)
			{
    
    
				is_AVL = false;
			}
			return max(RHeight, LHeight) + 1;
		}

		bool _IsAVLTree(Node* root)
		{
    
    
			if (root == nullptr)
			{
    
    
				return true;
			}
			int RHeight = Height(root->_right);
			int LHeight = Height(root->_left);

			if (abs(RHeight - LHeight) > 1 || root->_bf != RHeight - LHeight)
			{
    
    
				return false;
			}

			return _IsAVLTree(root->_left) && _IsAVLTree(root->_right);
		}

		void RotateLR(Node* parent)
		{
    
    
			Node* cur = parent->_left;
			Node* cur_right = cur->_right;
			int CR_bf = cur_right->_bf;

			RotateL(cur);
			RotateR(parent);

			if (CR_bf == 0)
			{
    
    
				parent->_bf = cur->_bf = cur_right->_bf = 0;
			}
			else if(CR_bf == 1)
			{
    
    
				cur->_bf = -1;
				parent->_bf = cur_right->_bf = 0;
			}
			else if (CR_bf == -1)
			{
    
    
				parent->_bf = 1;
				cur->_bf = cur_right->_bf = 0;
			}
			else
			{
    
    
				cout << __LINE__ << ":" << endl;
				perror("平衡因子有误");
				exit(-1);
			}
		}
		void RotateRL(Node* parent)
		{
    
    
			Node* cur = parent->_right;
			Node* cur_left = cur->_left;

			//CL——CurLeft
			int CL_bf = cur_left->_bf;
			RotateR(cur);
			RotateL(parent);

			if (CL_bf == 0)
			{
    
    
				cur->_bf = parent->_bf = cur_left->_bf = 0;
			}
			else if (CL_bf == 1)
			{
    
    
				parent->_bf = -1;
				cur->_bf = cur_left->_bf = 0;
			}
			else if(CL_bf == -1)
			{
    
    
				cur->_bf = 1;
				parent->_bf = cur_left->_bf = 0;
			}
			else
			{
    
    
				cout << __LINE__ << ":" << endl;
				perror("平衡因子有误");
				exit(-1);
			}
		}

		void RotateL(Node* parent)
		{
    
    
			//画图分析:
			//操作的结点有cur,cur_left,ppnode
			Node* cur = parent->_right;
			Node* cur_left = cur->_left;
			//将parent的右节点改为cur_left
			parent->_right = cur_left;
			//改变cur_left父节点的转向
			//cur_left可能为空
			if (cur_left != nullptr)
			{
    
    
				cur_left->_parent = parent;
			}
			//将parent链接在cur的左边
			//为了更新cur的parent需要保存parent的父节点
			Node* ppnode = parent->_parent;

			cur->_left = parent;
			parent->_parent = cur;

			//ppnode可能为空
			if (ppnode == nullptr)
			{
    
    
				//需要修改根节点
				_root = cur;
				cur->_parent = nullptr;
			}
			else
			{
    
    
				//改变ppnode的指向
				if (ppnode->_left == parent)
				{
    
    
					ppnode->_left = cur;
				}
				else
				{
    
    
					ppnode->_right = cur;
				}
				cur->_parent = ppnode;

			}

			//更新平衡因子
			cur->_bf = parent->_bf = 0;

		}
		void RotateR(Node* parent)
		{
    
    
			//操作的结点
			Node* cur = parent->_left;
			Node* cur_right = cur->_right;

			//第一步:将cur_right链接到parent的left
			parent->_left = cur_right;
			//更改cur_right的父节点
			//注意:cur_right可能为空
			if (cur_right != nullptr)
			{
    
    
				cur_right->_parent = parent;
			}
			//第二步:将parent链接到cur的右结点。
			//先保存一下parent的父节点
			Node* ppnode = parent->_parent;

			cur->_right = parent;
			parent->_parent = cur;
			//ppnode为空说明需要修改根节点
			if (ppnode == nullptr)
			{
    
    
				_root = cur;
				cur->_parent = nullptr;
			}
			else
			{
    
    
				if (ppnode->_left == parent)
				{
    
    
					ppnode->_left = cur;
				}
				else
				{
    
    
					ppnode->_right = cur;
				}

				cur->_parent = ppnode;
			}
			
			//更新平衡因子
			cur->_bf = parent->_bf = 0;

		}
		Node* _root = nullptr;
	};
};

Resumir

 Los árboles AVL también tienen operaciones de eliminación. Agregaré más cuando el blogger esté libre. En términos generales, para los árboles AVL, solo necesita comprender un tipo de rotación simple y un tipo de rotación doble, y agregar un poco de procesamiento de escritura fino. No es difícil, pero sí difícil, la dificultad radica en la discusión de clasificación + dibujo .Eso es todo por lo que compartimos hoy. Si lo encuentras útil, ¡dale un me gusta y anímalo!

Supongo que te gusta

Origin blog.csdn.net/Shun_Hua/article/details/132787902
Recomendado
Clasificación