目录

AVL树的插入(包含更新平衡因子)

子树的旋转

子树的左旋转

子树的右旋转

左右双旋

右左双旋

求树的高度

判断是否为平衡二叉树

层序遍历

代码总览


AVL树的插入(包含更新平衡因子)

bool Insert(const pair<K, V>& kv){//1.搜索树的规则插入//2.看是是否违反平衡规则,如果违反就需要处理:旋转if (_root == nullptr){_root = new Node(kv);_root->_bf = 0;return true;}Node* parent = nullptr;Node* cur = _root;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->_right){parent->_bf++;}else{parent->_bf--;}//是否继续更新?if (parent->_bf == 0)//1 or -1 ->插入节点填上了矮的那边{//高度不变,更新结束break;}else if(parent->_bf == 1 || parent->_bf == -1)//0 -> 1 or -1插入节点导致一边变高了 {//子树的高度变了,继续更新祖先cur = cur->_parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2)//-1 or 1 -> 2or-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)//左右双旋{RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1)//右左双旋{RotateRL(parent);}break;}else{//插入之前AVL树就存在不平衡子树,平衡因子的绝对值>=2的节点assert(false);}}return true;}

子树的旋转

子树的左旋转

 void RotateL(Node* parent)//左单旋{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if(subRL)subRL->_parent = parent;//易错Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;//易错if (parent == _root){_root = subR;_root->_parent = nullptr;}else{if (parent == ppNode->_left){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}//更新平衡因子parent->_bf = 0;subR->_bf = 0;}

子树的右旋转

 void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;//易错Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;//易错if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (parent == ppNode->_left){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}//更新平衡因子parent->_bf = 0;subL->_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 == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if(bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{//subLR->_bf旋转前就有问题assert(false);}}

右左双旋

void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subRL->_bf = 0;parent->_bf = 0;subR->_bf = 0;}else if (bf == 1){subRL->_bf = 0;parent->_bf = -1;subR->_bf = 0;}else if (bf == -1){subRL->_bf = 0;parent->_bf = 0;subRL->_bf = 1;}else{//subLR->_bf旋转前就有问题assert(false);}}

求树的高度

 int _Height(Node* root){if (root == nullptr)return 0;int lh = _Height(root->_left);int rh = _Height(root->_right);return lh > rh ? lh + 1 : rh + 1;}int Height(){return _Height(_root);}

判断是否为平衡二叉树

bool _IsBalanceTree(Node* root){// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot节点的平衡因子:即pRoot左右子树的高度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者// pRoot平衡因子的绝对值超过1,则一定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "节点平衡因子异常" << endl;return false;}if (diff != root->_bf){cout << root->_kv.first << "节点平衡因子不符合实际" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树一定是AVL树return _IsBalanceTree(root->_left)&& _IsBalanceTree(root->_right);}bool IsBalanceTree(){return _IsBalanceTree(_root);}

层序遍历

vector<vector<int>> levelOrder() {vector<vector<int>> vv;if (_root == nullptr)return vv;queue<Node*>q;int levelSize = 1;q.push(_root);while (!q.empty()){// levelSize控制一层一层出vector<int> levelV;while (levelSize--){Node* front = q.front();q.pop();levelV.push_back(front->_kv.first);if (front->_left)q.push(front->_left);if (front->_right)q.push(front->_right);}vv.push_back(levelV);for (auto e : levelV){cout << e << " ";}cout << endl;// 上一层出完,下一层就都进队列levelSize = q.size();}return vv;}

代码总览

#pragma once
#include<assert.h>
#include<vector>
#include<time.h>
#include<queue>template<class K,class V>
struct AVLTreeNode
{pair<K, V>* _kv;AVLTreeNode<K, V>* _left;AVLTreeNode<K, V>* _right;AVLTreeNode< K,V>*_parent;//左右子树高度差int _bf; //balence factor 平衡因子AVLTreeNode(const pair<K, V>& kv)//构造函数:_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr),_bf(0){}//AVL树并没有规定必须要实现平衡因子//只是一个实现的选择,方便控制平衡
};template<class K,class V>
class AVLTree
{typedef AVLTreeNode<K, V>Node;
public:bool Insert(const pair<K, V>& kv){//1.搜索树的规则插入//2.看是是否违反平衡规则,如果违反就需要处理:旋转if (_root == nullptr){_root = new Node(kv);_root->_bf = 0;return true;}Node* parent = nullptr;Node* cur = _root;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->_right){parent->_bf++;}else{parent->_bf--;}//是否继续更新?if (parent->_bf == 0)//1 or -1 ->插入节点填上了矮的那边{//高度不变,更新结束break;}else if(parent->_bf == 1 || parent->_bf == -1)//0 -> 1 or -1插入节点导致一边变高了 {//子树的高度变了,继续更新祖先cur = cur->_parent;parent = parent->_parent;}else if (parent->_bf == 2 || parent->_bf == -2)//-1 or 1 -> 2or-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)//左右双旋{RotateLR(parent);}else if (parent->_bf == 2 && cur->_bf == -1)//右左双旋{RotateRL(parent);}break;}else{//插入之前AVL树就存在不平衡子树,平衡因子的绝对值>=2的节点assert(false);}}return true;}private:void RotateL(Node* parent)//左单旋{Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if(subRL)subRL->_parent = parent;//易错Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;//易错if (parent == _root){_root = subR;_root->_parent = nullptr;}else{if (parent == ppNode->_left){ppNode->_left = subR;}else{ppNode->_right = subR;}subR->_parent = ppNode;}//更新平衡因子parent->_bf = 0;subR->_bf = 0;}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;//易错Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;//易错if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (parent == ppNode->_left){ppNode->_left = subL;}else{ppNode->_right = subL;}subL->_parent = ppNode;}//更新平衡因子parent->_bf = 0;subL->_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 == 0){parent->_bf = 0;subL->_bf = 0;subLR->_bf = 0;}else if (bf == 1){parent->_bf = 0;subL->_bf = -1;subLR->_bf = 0;}else if(bf == -1){parent->_bf = 1;subL->_bf = 0;subLR->_bf = 0;}else{//subLR->_bf旋转前就有问题assert(false);}}void RotateRL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == 0){subRL->_bf = 0;parent->_bf = 0;subR->_bf = 0;}else if (bf == 1){subRL->_bf = 0;parent->_bf = -1;subR->_bf = 0;}else if (bf == -1){subRL->_bf = 0;parent->_bf = 0;subRL->_bf = 1;}else{//subLR->_bf旋转前就有问题assert(false);}}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}int _Height(Node* root){if (root == nullptr)return 0;int lh = _Height(root->_left);int rh = _Height(root->_right);return lh > rh ? lh + 1 : rh + 1;}bool _IsBalanceTree(Node* root){// 空树也是AVL树if (nullptr == root)return true;// 计算pRoot节点的平衡因子:即pRoot左右子树的高度差int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);int diff = rightHeight - leftHeight;// 如果计算出的平衡因子与pRoot的平衡因子不相等,或者// pRoot平衡因子的绝对值超过1,则一定不是AVL树if (abs(diff) >= 2){cout << root->_kv.first << "节点平衡因子异常" << endl;return false;}if (diff != root->_bf){cout << root->_kv.first << "节点平衡因子不符合实际" << endl;return false;}// pRoot的左和右如果都是AVL树,则该树一定是AVL树return _IsBalanceTree(root->_left)&& _IsBalanceTree(root->_right);}public:void InOrder(){_InOrder(_root);cout << endl;}vector<vector<int>> levelOrder() {vector<vector<int>> vv;if (_root == nullptr)return vv;queue<Node*>q;int levelSize = 1;q.push(_root);while (!q.empty()){// levelSize控制一层一层出vector<int> levelV;while (levelSize--){Node* front = q.front();q.pop();levelV.push_back(front->_kv.first);if (front->_left)q.push(front->_left);if (front->_right)q.push(front->_right);}vv.push_back(levelV);for (auto e : levelV){cout << e << " ";}cout << endl;// 上一层出完,下一层就都进队列levelSize = q.size();}return vv;}bool IsBalanceTree(){return _IsBalanceTree(_root);}int Height(){return _Height(_root);}private:Node* _root = nullptr;
};void TestAVLTree1()
{//int a[] = { 1, 2, 3, 4, 5, 6, 7, 8 };int a[] = { 30,29,28,27,26,25,24,11,8,7,6,5,4,3,2,1 };AVLTree<int, int> t;for (auto e : a){t.Insert(make_pair(e, e));}t.levelOrder();
}void TestAVLTree2()
{const size_t N = 1024 * 1024 * 10;vector<int> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; ++i){//v.push_back(rand());v.push_back(i);}AVLTree<int, int> t;for (auto e : v){t.Insert(make_pair(e, e));}//t.levelOrder();//cout << endl;cout << "是否平衡?" << t.IsBalanceTree() << endl;cout << "高度:" << t.Height() << endl;//t.InOrder();
}

C++ AVL树(补充)相关推荐

  1. 【从蛋壳到满天飞】JS 数据结构解析和算法实现-AVL树(一)

    前言 [从蛋壳到满天飞]JS 数据结构解析和算法实现,全部文章大概的内容如下: Arrays(数组).Stacks(栈).Queues(队列).LinkedList(链表).Recursion(递归思 ...

  2. 一种基于平衡二叉树(AVL树)插入、查找和删除的简易图书管理系统

    目录 1. 需求分析 2. 项目核心设计 2.1 结点插入 2.2 结点删除 3 测试结果 4 总结分析 4.1 调试过程中的问题是如何解决的,以及对设计与实现的回顾讨论和分析 4.2 算法的时间和空 ...

  3. 对AVL树和红黑树的个人理解

    都说编程算法很重要,可真没见几个.NET程序员研究算法的.这些日子非主流地研究了一些小算法,红黑树和AVL树算是其中复杂的了,但实际也就二三百行代码.悲催的是,网上根本找不到C#的理想版本(包括国外网 ...

  4. 3. 数据结构--二叉树 BST AVL树 Huffman

    数据结构–二叉树 KEY:(不敢相信没有堆-) 二叉树的定义及其主要特征 ☑️ 二叉树的顺序存储结构和链式存储结构实现 二叉树的遍历及应用 二叉排序(查找.检索)树 (BST) 平衡的二叉检索树- A ...

  5. AVL树(艾薇儿树)

    接上章:二叉搜索树(Binary Search Tree). 通过二叉搜索树的学习,我们发现,二叉搜索树节点的添加和删除都是随机的,这里就会产生一种特殊情况,如下图所示: 001.jpg 此种情况,是 ...

  6. PTA 线性结构/AVL树/哈夫曼树错题

    1.稀疏矩阵压缩存储后,必会失去随机存取功能. T F 解析:稀疏矩阵的存储方式是将数据压缩存储进一维数组,数组下标与之前的不相同了,想要某一元素需要根据公式计算它的下标,所以说是失去了随机存取的功能 ...

  7. AVL树、splay树(伸展树)和红黑树比较

    AVL树.splay树(伸展树)和红黑树比较 一.AVL树: 优点:查找.插入和删除,最坏复杂度均为O(logN).实现操作简单 如过是随机插入或者删除,其理论上可以得到O(logN)的复杂度,但是实 ...

  8. 算法基础知识科普:8大搜索算法之AVL树(上)

    前段时间介绍了二叉搜索树(BST),我们知道这种搜索结构存在的弊端是对输入序列存在强依赖,若输入序列基本有序,则BST近似退化为链表.这样就会大大降低搜索的效率.AVL树以及Red-Black树就是为 ...

  9. 【漫画】以后在有面试官问你AVL树,你就把这篇文章扔给他。

    S 推荐阅读 对于另一半,你真正的爱过吗? 背景 西天取经的路上,一样上演着编程的乐趣..... 1.若它的左子树不为空,则左子树上所有的节点值都小于它的根节点值. 2.若它的右子树不为空,则右子树上 ...

最新文章

  1. 实时传输协议(RTP)
  2. java怎么测试dao_java-Mockito使用模拟对象测试DAO
  3. 【NLP】 聊聊NLP中的attention机制
  4. Android Fragments 详细使用
  5. 高通写号工具_高通推出桌面平台新ARM处理器并认为我们的电脑性能没必要那么高...
  6. 《Java8实战》笔记汇总
  7. 二叉树的几种遍历方法
  8. HDU 4336 Card Collector(状压 + 概率DP 期望)题解
  9. Linux下端口占用解决方法
  10. 开课吧:分享C++代码的整洁之道!
  11. 整理转载:分枝定界图解(含 Real-Time Loop Closure in 2D LIDAR SLAM论文部分解读及BB代码部分解读)
  12. bat文件启动虚拟环境然后继续在虚拟环境里进行操作采用CALL
  13. 关于redis key命名规范的设计
  14. 二叉树(链表)的相关操作
  15. 软件测试 测试用例笔记
  16. 机械制图与计算机绘图习题集第二版答案,机械制图与计算机绘图习题集(第2版)-曾令宜.pdf...
  17. 【Matlab应用】:相控阵天线方向图合成及波束扫描算法实现
  18. 如何挑选微信第三方开发商
  19. HD44780http://blog.sina.com.cn/s/blog_61b6e08b01016xif.html
  20. 赖大师新文章 :Xilinx 开箱-KV260相机,两个小时轻松搞定,文章不能用我坐飞机过去帮你调哈。

热门文章

  1. 我们为什么要将图片转换成PDF?
  2. 数据库连接池 Connection Pool 是什么,做什么
  3. html播放rmvb,用windows media player 播放rmvb 和mov
  4. 诺基亚将裁员万人 风雨飘摇中该何去何从
  5. vue3中使用swiper7
  6. 雷达视频化安防软件——RadarVison
  7. JavaMail(一)搜索邮件
  8. C语言,输入硬币面值和硬币个数,换成输出一分,两份,五分硬币亦硬币个数
  9. 植物肉品牌Z-Rou株肉举办杭州超级粉丝见面会,正式宣告进入杭州市场
  10. 成都IT招聘网站集锦