当前位置: 首页 > news >正文

AVL树的模拟实现(插入,验证)

目录

前言

AVL树的概念

AVL树的旋转

旋转

左旋

右旋

左右旋

右左旋

AVL的insert的实现

AVL的验证

完整代码

总结


前言

本文会先将AVL树的旋转进行讲解, 然后再对代码进行实现和展示。 

AVL树的概念

首先 AVL树 是一种平衡树, 平衡树是在二叉搜索树的基础上进行平衡 , AVL树是一种严格平衡(即 左右子树的高度差 不超过1)。 既然AVL树是在二叉搜索树的基础进行平衡的,因此AVL树也具备二叉搜索树的基本功能。

AVL树的旋转

我们用一个 平衡因子 _bf 对AVL树进行维护。平衡因子_bf 存储 左右子树的高度差。 此文以 _bf = 左子树高度 - 右子树高度    为基准。

旋转

什么时候进行旋转? 当插入数据时, 可能进行旋转。 我们记 dest 为 要插入节点的位置, parent为dest节点的父节点。 而AVL树插入数据前具体有三种情况,如下图.

显然, 当在图【2】插入数据时,是必定不会旋转的。 而在图【1】的 3 ,4 位置, 以及图【3】的1,2位置插入数据时,也是必定不会旋转的

左旋

当在图【3】的 4 位置 插入会进左旋。 

左旋的流程:

代码实现

void RotateL(Node* parent)
{Node* pparent = parent->_parent;Node* Rchild = parent->_right;Node* RLchild = Rchild->_left;if(RLchild != nullptr)RLchild->_parent = parent;parent->_right = RLchild;Rchild->_parent = pparent;if (pparent != nullptr){if (parent == pparent->_left) pparent->_left = Rchild;else pparent->_right = Rchild;}else{_root = Rchild;}Rchild->_left = parent;parent->_parent = Rchild;Rchild->_bf = parent->_bf = 0;}
右旋

在图【1】的1位置插入 会进行右旋

右旋的流程:

代码实现:

void RotateR(Node* parent)
{Node* pparent = parent->_parent;Node* Lchild = parent->_left;Node* LRchild = Lchild->_right;if(LRchild != nullptr) LRchild->_parent = parent;parent->_left = LRchild;Lchild->_parent = pparent;if (pparent != nullptr){if (parent == pparent->_left) pparent->_left = Lchild;else pparent->_right = Lchild;}else{_root = Lchild;}parent->_parent = Lchild;Lchild->_right = parent;parent->_bf = Lchild->_bf = 0;
}
左右旋

在图【1】的2位置插入,需要左右旋。

将图【1】的2位置进行展开,如下图。

左右旋的流程

void RotateLR(Node* parent)
{Node* Lchild = parent->_left;Node* LRchild = Lchild->_right;RotateL(Lchild);RotateR(parent);if (LRchild->_bf == -1){parent->_bf = 1;Lchild->_bf = LRchild->_bf = 0;}else{Lchild->_bf = -1;LRchild->_bf = parent->_bf = 0;}
}
右左旋

在图【3】的3位置进行插入,进行右左旋

对图【3】的3位置进行展开

右左旋转流程:

代码实现:

	void RotateRL(Node* parent){Node* Rchild = parent->_right;Node* RLchild = Rchild->_left;RotateR(Rchild);RotateL(parent);if (RLchild->_bf == -1){RLchild->_bf = parent->_bf = 0;Rchild->_bf = 1;}else{parent->_bf = -1;RLchild = Rchild = 0;}}

AVL的insert的实现

插入成功返回true,插入失败返回false

bool insert(const T& x)
{if (_root == nullptr){_root = new Node(x);return true;}Node* node = _root;Node* parent = nullptr;while (node){if (x < node->_val){parent = node;node = node->_left;}else if (x > node->_val){parent = node;node = node->_right;}else{return false;}}Node* child = new Node(x);if (x < parent->_val){parent->_left = child;child->_parent = parent;parent->_bf--;}else{parent->_right = child;child->_parent = parent;parent->_bf++;}while (parent){if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){child = parent;parent = child->_parent;if (parent != nullptr){if (child == parent->_left) parent->_bf--;else parent->_bf++;}}else if (parent->_bf == 2 && child->_bf == 1){//左单旋RotateL(parent);}else if (parent->_bf == -2 && child->_bf == -1){//右单旋RotateR(parent);}else if (parent->_bf == 2 && child->_bf == -1){//右左双旋RotateRL(parent);}else if (parent->_bf == -2 && child->_bf == 1){//左右双旋转RotateLR(parent);}}return true;}

AVL的验证

	void IsAVLTree(){if (IsAVLTree(_root)) cout << "是AVL树" << endl;else cout << "不是AVL树" << endl;}
private:int GetHeight(Node* root){if (root == nullptr) return 0;int L = GetHeight(root->_left);int R = GetHeight(root->_right);return L > R ? L + 1 : R + 1;}bool IsAVLTree(Node* root){if (root == nullptr) return true;int L_Height = GetHeight(root->_left);int R_Height = GetHeight(root->_right);if (abs(L_Height - R_Height) > 1) return false;return IsAVLTree(root->_left) && IsAVLTree(root->_right);}

完整代码

template<class T>
struct Node
{T _val;Node<T>* _left;Node<T>* _right;Node<T>* _parent;int _bf = 0;Node(const T& x = T()): _val(x), _left(nullptr),_right(nullptr),_parent(nullptr){}
};template<class T>
class AVLTree
{typedef Node<T> Node;
private:Node* _root = nullptr;
public:bool insert(const T& x){if (_root == nullptr){_root = new Node(x);return true;}Node* node = _root;Node* parent = nullptr;while (node){if (x < node->_val){parent = node;node = node->_left;}else if (x > node->_val){parent = node;node = node->_right;}else{return false;}}Node* child = new Node(x);if (x < parent->_val){parent->_left = child;child->_parent = parent;parent->_bf--;}else{parent->_right = child;child->_parent = parent;parent->_bf++;}while (parent){if (parent->_bf == 0){break;}else if (parent->_bf == 1 || parent->_bf == -1){child = parent;parent = child->_parent;if (parent != nullptr){if (child == parent->_left) parent->_bf--;else parent->_bf++;}}else if (parent->_bf == 2 && child->_bf == 1){//左单旋RotateL(parent);}else if (parent->_bf == -2 && child->_bf == -1){//右单旋RotateR(parent);}else if (parent->_bf == 2 && child->_bf == -1){//右左双旋RotateRL(parent);}else if (parent->_bf == -2 && child->_bf == 1){//左右双旋转RotateLR(parent);}}return true;}void Order(){Order(_root);cout << endl;}void IsAVLTree(){if (IsAVLTree(_root)) cout << "是AVL树" << endl;else cout << "不是AVL树" << endl;}
private:int GetHeight(Node* root){if (root == nullptr) return 0;int L = GetHeight(root->_left);int R = GetHeight(root->_right);return L > R ? L + 1 : R + 1;}bool IsAVLTree(Node* root){if (root == nullptr) return true;int L_Height = GetHeight(root->_left);int R_Height = GetHeight(root->_right);if (abs(L_Height - R_Height) > 1) return false;return IsAVLTree(root->_left) && IsAVLTree(root->_right);}void Order(Node* root){if (root == nullptr) return;Order(root->_left);cout << root->_val << ' ';Order(root->_right);}void RotateL(Node* parent){Node* pparent = parent->_parent;Node* Rchild = parent->_right;Node* RLchild = Rchild->_left;if(RLchild != nullptr)RLchild->_parent = parent;parent->_right = RLchild;Rchild->_parent = pparent;if (pparent != nullptr){if (parent == pparent->_left) pparent->_left = Rchild;else pparent->_right = Rchild;}else{_root = Rchild;}Rchild->_left = parent;parent->_parent = Rchild;Rchild->_bf = parent->_bf = 0;}void RotateR(Node* parent){Node* pparent = parent->_parent;Node* Lchild = parent->_left;Node* LRchild = Lchild->_right;if(LRchild != nullptr) LRchild->_parent = parent;parent->_left = LRchild;Lchild->_parent = pparent;if (pparent != nullptr){if (parent == pparent->_left) pparent->_left = Lchild;else pparent->_right = Lchild;}else{_root = Lchild;}parent->_parent = Lchild;Lchild->_right = parent;parent->_bf = Lchild->_bf = 0;}void RotateRL(Node* parent){Node* Rchild = parent->_right;Node* RLchild = Rchild->_left;RotateR(Rchild);RotateL(parent);if (RLchild->_bf == -1){RLchild->_bf = parent->_bf = 0;Rchild->_bf = 1;}else{parent->_bf = -1;RLchild = Rchild = 0;}}void RotateLR(Node* parent){Node* Lchild = parent->_left;Node* LRchild = Lchild->_right;RotateL(Lchild);RotateR(parent);if (LRchild->_bf == -1){parent->_bf = 1;Lchild->_bf = LRchild->_bf = 0;}else{Lchild->_bf = -1;LRchild->_bf = parent->_bf = 0;}}
};

总结

实际上AVL树的实现的难点在于 AVL树旋转,搞明白旋转,剩下的就明了了


http://www.mrgr.cn/news/24866.html

相关文章:

  • 计算机三级网络技术总结 第十一章网络管理技术
  • 「数学::质数」埃氏筛|欧拉筛(埃拉托斯特尼筛法|线性筛法)/ LeetCode 204(C++)
  • LJS送给WSW的生日礼物——happy birthday to my dear friend————(作者:LJS)
  • 速盾:cdn加速效果明显吗?
  • 【佳学基因检测】在织梦网站中, 创建或修改目录:/var/www/html/cp 失败! DedeTag Engine Create File False
  • 【Java自动化学习】接口自动化
  • Shell脚本计算π的近似值
  • Visual Studio安装教程
  • 在长度 2N 的数组中找出重复 N 次的元素
  • 新的 PIXHELL 攻击从隔离系统中窃取机密
  • scene graph generation 计算mean recall数据的过程:
  • Java重修笔记 第五十四天 坦克大战(三)事件处理机制
  • 手写Promise
  • 贪心算法day29|134. 加油站(理解有难度)、135. 分发糖果、860. 柠檬水找零、406. 根据身高重建队列
  • 基于 PyTorch 和 TensorFlow 的口罩检测与人脸识别系统
  • 在 PyTorch 中,除了 pad_sequence 还有哪些其他处理序列数据的函数?时间序列数据 预处理
  • 什么是 PD 电压诱骗?
  • R语言统计分析——功效分析2(t检验,ANOVA)
  • 【 html+css 绚丽Loading 】000047 玄武流转盘
  • [综述笔记]Federated learning for medical image analysis: A survey