C++从入门到起飞之——AVL树 全方位剖析!
🌈个人主页:秋风起,再归来~
🔥系列专栏:C++从入门到起飞
🔖克心守己,律己则安
目录
1. AVL的概念
2. AVL树的实现
2.1 AVL树的结构
2.2 AVL树的插⼊
>AVL树插⼊⼀个值的⼤概过程
>平衡因⼦更新
>插⼊结点及更新平衡因⼦的代码实现
2.3 旋转
2.3.1 旋转的原则
2.3.2 右单旋
2.3.3 右单旋代码实现
2.3.4 左单旋
2.3.5 左单旋代码实现
2.3.6 左右双旋
2.3.7左右双旋代码实现
2.3.8 右左双旋
2.3.9 右左双旋代码实现
2.4 AVL树的查找
2.5 AVL树平衡检测
3. 源码
4、完结散花
1. AVL的概念
• AVL树是最先发明的⾃平衡⼆叉查找树,AVL是⼀颗空树,或者具备下列性质的⼆叉搜索树:它的 左右⼦树都是AV树,且左右⼦树的⾼度差的绝对值不超过1。AVL树是⼀颗⾼度平衡搜索⼆叉树, 通过控制⾼度差去控制平衡。
• AVL树得名于它的发明者G.M.Adelson-Velsky和E.M.Landis是两个前苏联的科学家,他们在1962 年的论⽂《An algorithm or the organization of information》中发表了它。
• AVL树实现这⾥我们引⼊⼀个平衡因⼦(balance factor)的概念,每个结点都有⼀个平衡因⼦,任何 结点的平衡因⼦等于右⼦树的⾼度减去左⼦树的⾼度,也就是说任何结点的平衡因⼦等于0/1/-1, AVL树并不是必须要平衡因⼦,但是有了平衡因⼦可以更⽅便我们去进⾏观察和控制树是否平衡, 就像⼀个⻛向标⼀样。
• 思考⼀下为什么AVL树是⾼度平衡搜索⼆叉树,要求⾼度差不超过1,⽽不是⾼度差是0呢?0不是更 好的平衡吗?画画图分析我们发现,不是不想这样设计,⽽是有些情况是做不到⾼度差是0的。⽐ 如⼀棵树是2个结点,4个结点等情况下,⾼度差最好就是1,⽆法作为⾼度差是0
• AVL树整体结点数量和分布和完全⼆叉树类似,⾼度可以控制在 ,那么增删查改的效率也可 以控制在,相⽐⼆叉搜索树有了本质的提升。
2. AVL树的实现
2.1 AVL树的结构
节点的结构:
template<class K,class V>
struct AVLTreeNode
{pair<K, V> _kv;AVLTreeNode* _parent;AVLTreeNode* _right;AVLTreeNode* _left;int _bf;//平衡因子AVLTreeNode(const pair<K,V>& kv):_kv(kv), _parent(nullptr), _right(nullptr),_left(nullptr),_bf(0){}
};
树的结构:
template<class K, class V>
class AVLTree
{
public:typedef AVLTreeNode<K,V> Node;//......private:Node* _root=nullptr;
};
2.2 AVL树的插⼊
>AVL树插⼊⼀个值的⼤概过程
1. 插⼊⼀个值按⼆叉搜索树规则进⾏插⼊。
2. 新增结点以后,只会影响祖先结点的⾼度,也就是可能会影响部分祖先结点的平衡因⼦,所以更新 从新增结点->根结点路径上的平衡因⼦,实际中最坏情况下要更新到根,有些情况更新到中间就可 以停⽌了,具体情况我们下⾯再详细分析。
3. 更新平衡因⼦过程中没有出现问题,则插⼊结束
4. 更新平衡因⼦过程中出现不平衡,对不平衡⼦树旋转,旋转后本质调平衡的同时,本质降低了⼦树 的⾼度,不会再影响上⼀层,所以插⼊结束
>平衡因⼦更新
更新原则:
• 平衡因⼦=右⼦树⾼度-左⼦树⾼度
• 只有⼦树⾼度变化才会影响当前结点平衡因⼦。
• 插⼊结点,会增加⾼度,所以新增结点在parent的右⼦树,parent的平衡因⼦++,新增结点在 parent的左⼦树,parent平衡因⼦--
• parent所在⼦树的⾼度是否变化决定了是否会继续往上更新
更新停⽌条件:
• 更新后parent的平衡因⼦等于0,更新中parent的平衡因⼦变化为-1->0或者1->0,说明更新前 parent⼦树⼀边⾼⼀边低,新增的结点插⼊在低的那边,插⼊后parent所在的⼦树⾼度不变,不会 影响parent的⽗亲结点的平衡因⼦,更新结束。
• 更新后parent的平衡因⼦等于1或-1,更新前更新中parent的平衡因⼦变化为0->1或者0->-1,说 明更新前parent⼦树两边⼀样⾼,新增的插⼊结点后,parent所在的⼦树⼀边⾼⼀边低,parent所 在的⼦树符合平衡要求,但是⾼度增加了1,会影响arent的⽗亲结点的平衡因⼦,所以要继续向上 更新。
• 更新后parent的平衡因⼦等于2或-2,更新前更新中parent的平衡因⼦变化为1->2或者-1->-2,说 明更新前parent⼦树⼀边⾼⼀边低,新增的插⼊结点在⾼的那边,parent所在的⼦树⾼的那边更⾼ 了,破坏了平衡,parent所在的⼦树不符合平衡要求,需要旋转处理,旋转的⽬标有两个:
1、把 parent⼦树旋转平衡。
2、降低parent⼦树的⾼度,恢复到插⼊结点以前的⾼度。所以旋转后也不 需要继续往上更新,插⼊结束。
>插⼊结点及更新平衡因⼦的代码实现
bool insert(const pair<K, V>& kv){//如果树为空,直接在根插入if (_root == nullptr){_root = new Node(kv);return true;}//树不为空,先按照搜索树规则找到插入位置Node* parent = nullptr;Node* cur = _root;while (cur){//插入的key小就往左走if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}//大就往右走else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else//不支持键值冗余{return false;}}//找到在parent插入的位置了cur = new Node(kv);if (kv.first < parent->_kv.first)parent->_left = cur;elseparent->_right = cur;//不要忘记链接新增节点的parentcur->_parent = parent;//开始更新平衡因子while (parent){if (parent->_left == cur)parent->_bf--;elseparent->_bf++;//_bf从1或-1到0,不会影响祖先节点if (parent->_bf == 0){break;}//_bf从0到1或-1,会影响祖先节点,继续向上更新else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}//平衡破坏,旋转恢复平衡else if (parent->_bf == 2 || parent->_bf == -2){//旋转逻辑//........break;//旋转完后,该节点的平衡因子为0,无需向上更新}else//非预想平衡因子,直接断死{assert(false);}}return true;}
2.3 旋转
2.3.1 旋转的原则
1. 保持搜索树的规则
2. 让旋转的树从不满⾜变平衡,其次降低旋转树的⾼度 旋转总共分为四种,左单旋/右单旋/左右双旋/右左双旋。
说明:下⾯的图中,有些结点我们给的是具体值,如10和5等结点,这⾥是为了⽅便讲解,实际中是什 么值都可以,只要⼤⼩关系符合搜索树的规则即可。
2.3.2 右单旋
具象图
抽象图
2.3.3 右单旋代码实现
//右单旋
void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;Node* pParent = parent->_parent;parent->_left = subLR;if(subLR)//如果不为空subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;if (pParent == nullptr){_root = subL;subL->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}subL->_parent = pParent;}parent->_bf = subL->_bf = 0;
}
2.3.4 左单旋
具象图
抽象图
2.3.5 左单旋代码实现
//左单旋
void RotateL(Node* parent)
{Node* pParent = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;subR->_left = parent;parent->_parent = subR;parent->_right = subRL;if (subRL)subRL->_parent = parent;if (pParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subR;}else{pParent->_right = subR;}subR->_parent = pParent;}parent->_bf = subR->_bf = 0;
}
2.3.6 左右双旋
具象图
抽象图
2.3.7左右双旋代码实现
//左右双旋
void RotateLR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;int bf = subLR->_bf;RotateL(parent->_left);RotateR(parent);if (bf == -1){subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if(bf == 1){subL->_bf = -1;parent->_bf = 0;subLR->_bf = 0;}else if (bf == 0){subL->_bf = 0;parent->_bf = 0;subLR->_bf = 0;}else{assert(false);}
}
2.3.8 右左双旋
2.3.9 右左双旋代码实现
//右左双旋
void RotateRL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;int bf = subRL->_bf;RotateR(parent->_right);RotateL(parent);if (bf == -1){subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 1){subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == 0){subR->_bf = 0;parent->_bf = 0;subRL->_bf = 0;}else{assert(false);}
}
2.4 AVL树的查找
按⼆叉搜索树逻辑实现即可,搜索效率为O(logN)
//查找
Node* find(const K& key)
{Node* cur = _root;while (cur){if (cur->_kv.first == key){return cur;}else if (key < cur->_kv.first){cur = cur->_left;}else{cur = cur->_right;}}return nullptr;
}
2.5 AVL树平衡检测
我们实现的AVL树是否合格,我们通过检查左右⼦树⾼度差的的程序进⾏反向验证,同时检查⼀下结点 的平衡因⼦更新是否出现了问题。
//中序遍历
Node* _Inorder(Node* root)
{if (root == nullptr)return nullptr;_Inorder(root->_left);cout << "{" << root->_kv.first << "," << root->_kv.second << "}" << endl;_Inorder(root->_right);return root;
}
//计算树的高度
int _Height(Node* root)
{if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
//计算节点的数量
int _Size(Node* root)
{if (root == nullptr)return 0;int CountL = _Size(root->_left);int CountR = _Size(root->_right);return CountL + CountR + 1;
}
//判断是否是AVL树
bool _IsBalanceTree(Node* root)
{//空树也是AVL树if (root == nullptr)return true;int LHeight = _Height(root->_left);int RHeight = _Height(root->_right);int ret = RHeight - LHeight;if (abs(ret) >= 2){cout << root->_kv.first << "高度差异常" << endl << "高度差为:" << ret << endl;return false;}if (ret != root->_bf){cout << root->_kv.first << "平衡因子异常" << endl;return false;}return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);
}
#include"AVLTree.h"
#include<vector>void TestRotate()
{AVLTree<int, int> t;// 常规的测试⽤例 //int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };// 特殊的带有双旋场景的测试⽤例 int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };for (auto e : a){t.insert({ e,e });}t.Inorder();cout << t.IsBalanceTree() << endl;
}
void TestTreeBalance()
{const int N = 1000;srand((unsigned int)time(nullptr));AVLTree<int, int> t;vector<int> v;for (int i = 0; i < N; i++){v.push_back(rand() + i);}for (auto e : v){t.insert({ e,e });}cout << t.Height() << endl;;cout << t.Size() << endl;cout << t.IsBalanceTree() << endl;
}int main()
{//TestRotate();TestTreeBalance();return 0;
}
3. 源码
#pragma once
#include<assert.h>
#include<iostream>
using namespace std;template<class K,class V>
struct AVLTreeNode
{pair<K, V> _kv;AVLTreeNode* _parent;AVLTreeNode* _right;AVLTreeNode* _left;int _bf;//平衡因子AVLTreeNode(const pair<K,V>& kv):_kv(kv), _parent(nullptr), _right(nullptr),_left(nullptr),_bf(0){}
};template<class K, class V>
class AVLTree
{
public:typedef AVLTreeNode<K,V> Node;//插入bool insert(const pair<K, V>& kv){//如果树为空,直接在根插入if (_root == nullptr){_root = new Node(kv);return true;}//树不为空,先按照搜索树规则找到插入位置Node* parent = nullptr;Node* cur = _root;while (cur){//插入的key小就往左走if (kv.first < cur->_kv.first){parent = cur;cur = cur->_left;}//大就往右走else if (kv.first > cur->_kv.first){parent = cur;cur = cur->_right;}else//不支持键值冗余{return false;}}//找到在parent插入的位置了cur = new Node(kv);if (kv.first < parent->_kv.first)parent->_left = cur;elseparent->_right = cur;//不要忘记链接新增节点的parentcur->_parent = parent;//开始更新平衡因子while (parent){if (parent->_left == cur)parent->_bf--;elseparent->_bf++;//_bf从1或-1到0,不会影响祖先节点if (parent->_bf == 0){break;}//_bf从0到1或-1,会影响祖先节点,继续向上更新else if (parent->_bf == 1 || parent->_bf == -1){cur = parent;parent = parent->_parent;}//平衡破坏,旋转恢复平衡else if (parent->_bf == 2 || parent->_bf == -2){//旋转逻辑//纯粹左边高进行右单旋if (parent->_bf == -2 && parent->_left->_bf == -1){RotateR(parent);}//纯粹右边高进行左单旋else if (parent->_bf == 2 && parent->_right->_bf == 1){RotateL(parent);}//不纯粹左边高进行左右双旋else if (parent->_bf == -2 && parent->_left->_bf == 1){RotateLR(parent);}//不纯粹右边高进行右左双旋else if (parent->_bf == 2 && parent->_right->_bf == -1){RotateRL(parent);}break;//旋转完后,该节点的平衡因子为0,无需向上更新}else//非预想平衡因子,直接断死{assert(false);}}return true;}//查找Node* find(const K& key){Node* cur = _root;while (cur){if (cur->_kv.first == key){return cur;}else if (key < cur->_kv.first){cur = cur->_left;}else{cur = cur->_right;}}return nullptr;}//中序遍历void Inorder(){_Inorder(_root);}//计算树的高度int Height(){return _Height(_root);}//计算树的节点个数int Size(){return _Size(_root);}//判断是否是AVL树bool IsBalanceTree(){return _IsBalanceTree(_root);}private://右单旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;Node* pParent = parent->_parent;parent->_left = subLR;if(subLR)//如果不为空subLR->_parent = parent;subL->_right = parent;parent->_parent = subL;if (pParent == nullptr){_root = subL;subL->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}subL->_parent = pParent;}parent->_bf = subL->_bf = 0;}//左单旋void RotateL(Node* parent){Node* pParent = parent->_parent;Node* subR = parent->_right;Node* subRL = subR->_left;subR->_left = parent;parent->_parent = subR;parent->_right = subRL;if (subRL)subRL->_parent = parent;if (pParent == nullptr){_root = subR;subR->_parent = nullptr;}else{if (pParent->_left == parent){pParent->_left = subR;}else{pParent->_right = subR;}subR->_parent = pParent;}parent->_bf = subR->_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 == -1){subL->_bf = 0;parent->_bf = 1;subLR->_bf = 0;}else if(bf == 1){subL->_bf = -1;parent->_bf = 0;subLR->_bf = 0;}else if (bf == 0){subL->_bf = 0;parent->_bf = 0;subLR->_bf = 0;}else{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 == -1){subR->_bf = 1;parent->_bf = 0;subRL->_bf = 0;}else if (bf == 1){subR->_bf = 0;parent->_bf = -1;subRL->_bf = 0;}else if (bf == 0){subR->_bf = 0;parent->_bf = 0;subRL->_bf = 0;}else{assert(false);}}//中序遍历Node* _Inorder(Node* root){if (root == nullptr)return nullptr;_Inorder(root->_left);cout << "{" << root->_kv.first << "," << root->_kv.second << "}" << endl;_Inorder(root->_right);return root;}//计算树的高度int _Height(Node* root){if (root == nullptr)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;}//计算节点的数量int _Size(Node* root){if (root == nullptr)return 0;int CountL = _Size(root->_left);int CountR = _Size(root->_right);return CountL + CountR + 1;}//判断是否是AVL树bool _IsBalanceTree(Node* root){//空树也是AVL树if (root == nullptr)return true;int LHeight = _Height(root->_left);int RHeight = _Height(root->_right);int ret = RHeight - LHeight;if (abs(ret) >= 2){cout << root->_kv.first << "高度差异常" << endl << "高度差为:" << ret << endl;return false;}if (ret != root->_bf){cout << root->_kv.first << "平衡因子异常" << endl;return false;}return _IsBalanceTree(root->_left) && _IsBalanceTree(root->_right);}private:Node* _root=nullptr;
};
4、完结散花
好了,这期的分享到这里就结束了~
如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~
如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~
我们下期不见不散~~
相关文章:

C++从入门到起飞之——AVL树 全方位剖析!
🌈个人主页:秋风起,再归来~🔥系列专栏:C从入门到起飞 🔖克心守己,律己则安 目录 1. AVL的概念 2. AVL树的实现 2.1 AVL树的结构 2.2 AVL树的插⼊ >AVL树插⼊⼀个值的⼤概过程 &…...

利用Fail2Ban增强Jupyter Notebook安全性以防范目录遍历攻击
利用Fail2Ban增强Jupyter Notebook安全性以防范目录遍历攻击 书接上回[^参见]一、目录遍历攻击(Directory Traversal Attack)二、日志记录的网络攻击示例分析三、配置 Fail2ban四、fail2ban-regex测试和验证正则表达式五、重启 Fail2Ban六、验证配置生效…...

智能贴身监测,健康生活建议,圆道妙医智能手表体验
如今热衷于运动和健康生活的爱好者越来越多,相关的赛事等活动也是逐年增多,很多朋友为了能够直观的了解自己的健康状况,都会配备一款智能手表,这样戴在身上就可以随时了解自己的心率、血氧等数据。最近我尝试了一款圆道妙医推出的…...

C++——AVL树
文章目录 一、AVL树的概念二、AVL树的实现1. AVL树的结构2. AVL树的插⼊2.1 AVL树插⼊⼀个值的⼤概过程2.2 平衡因⼦更新更新原则更新停止条件 2.3 插⼊结点及更新平衡因⼦的代码实现 3. 旋转旋转的原则右单旋左单旋左右双旋右左双旋 4.高度5.结点个数6.判断是否是AVL树7. 中序…...

极市平台 | 无人机相关开源数据集资源汇总
本文来源公众号“极市平台”,仅用于学术分享,侵权删,干货满满。 原文链接:无人机相关开源数据集资源汇总 本文介绍几个无人机有关的开源数据集,内附下载链接。 UAV Delievery 无人机轨迹数据集 下载链接ÿ…...

React和Vue区别,以及注意事项
目录 一、语法和框架特性的差异 二、开发习惯和注意事项 三、特别注意事项 一、语法和框架特性的差异 模板语法: Vue使用了类似于传统HTML的模板语法,通过双大括号{{ }}进行插值,而React则使用了JSX语法。在Vue中,你可以直接在…...

光伏项目难管理的问题如何解决?
1.数字化管理平台的应用 数字化是当前解决光伏项目管理难题的关键手段之一。通过建立统一的数字化管理平台,可以实现对光伏电站的远程监控、数据分析、故障预警及运维调度等功能。这类平台通常集成有智能算法,能够实时分析电站运行数据,及时…...

图片美化SDK解决方案,赋能H5与小程序极致体验
无论是社交媒体分享、电商产品展示,还是个人日常生活的记录,一张经过精心美化的图片总能瞬间吸引眼球,传递出更加丰富和动人的信息。如何在不增加应用体积、不牺牲用户体验的前提下,为H5页面和小程序提供媲美原生APP的图片美化功能…...

Kron Reduction消去法如何操作,矩阵推导过程
三阶矩阵消去单节点 在电力系统中,母线上的电流注入始终为0,这样的节点可以通过一定的方法消除。以三节点为例,假设注入节点3的电流为0,则: [ I 1 I 2 I 3 ] = [ I 1 I 2 0 ] = [ Y 11 Y 12 Y 13 Y 21 Y 22 Y 23 Y 31 Y 32 Y 33 ] [ V 1 V 2 V 3 ] \left[\begin{array}{…...

实时开放词汇目标检测(论文复现)
实时开放词汇目标检测(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 实时开放词汇目标检测(论文复现)概述模型框架使用方式配置环境训练和评估训练评估 演示效果Gradio Demo 概述 YOLO-World是由腾讯人工智能实验…...

陪诊小程序搭建:打造便利的陪诊环境
陪诊行业作为一个新兴行业,随着老龄化的严重,在近几年中需求量日益旺盛。陪诊师为大众的就医提供了极大的便利性,在看病难、医疗资源紧张方面发挥了积极作用。 在陪诊行业的快速发展下,陪诊小程序为行业带来了便捷的模式…...

Qt5.15.2静态编译 MinGW with static OpenSSL
如果想用VS2017编译,可参考:Qt5.15.2静态编译 VS2017 with static OpenSSL 一.环境 系统:Windows 10 专业版 64位 编译器:MinGW 8.1.0 第三方工具:perl,ruby和python PS:经验证,用MinGW 12.1.0来编译Qt5.15.2会报错 我用Phthon 2.7.18虽然可以编过,但是强烈建议Pyth…...

Linux Ubuntu dbus CAPI ---- #include<dbus.h>出现“无法打开源文件dbus/xxx.h“的问题
一、确保已安装dbus库和CAPI sudo apt-get install libdbus-1-dev 二、在c_cpp_properties.json的includePath中是否配置了dbus库依赖文件所在的路径 三、编译一个简单的dbus代码,在编译过程中只要出现.h文件找不到的情况,就使用下列命令找到.h文件路径…...

React01 开发环境搭建
React 开发环境搭建 一、创建 React 项目二、项目精简 一、创建 React 项目 执行下述命令创建 react 项目 blu-react-basis npx create-react-app blu-react-basis项目目录结构如下: 执行下述命令启动项目 npm run start启动效果如下: 二、项目精简 …...

数据结构之旅(顺序表)
前言: Hello,各位小伙伴们我们在过去的60天里学完了C语言基本语法,由于小编在准备数学竞赛,最近没有给大家更新,并且没有及时回复大家的私信,小编在这里和大家说一声对不起!,小编这几天会及时给大家更新初阶数据结构的内容,然后我们来学习今天的内容吧! 一. 顺序表的概念和结…...

掌握 C# 内存管理与垃圾回收机制
内存管理是每个开发者需要了解的关键部分,特别是在构建高性能应用时。在 C# 中,垃圾回收(Garbage Collection, GC) 机制自动管理内存分配和释放,大大简化了内存管理的复杂性。然而,理解值类型与引用类型的区…...

【JavaEE】——初始网络原理
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 一:局域网 1:概念 二:局域网的连接方式 1:网线直连 …...

Nginx和Lua配合使用
在NGINX中使用Lua进行开发时,可以通过不同的配置块来指定Lua脚本的执行位置。这些配置块被称为“phase hooks”,即阶段挂钩。每个阶段挂钩都有其特定的作用时间和目的。以下是NGINX Lua模块中常见的配置指令及其用途: 常见的Phase Hooks 1.a…...

程序化交易是什么,它有哪些优势,需要注意什么?
炒股自动化:申请官方API接口,散户也可以 python炒股自动化(0),申请券商API接口 python炒股自动化(1),量化交易接口区别 Python炒股自动化(2):获取…...

水库抽样算法(大数据算法作业)
时隔一个多月,终于想起来写大数据算法基础的实验报告,主要是快截止了,hh 这两天加急把这个报告写完了~ 接下来,写一写证明过程(参考书籍:高等教育出版社《数据科学与工程算法基础》)主要代码以…...

SHCTF-2024-week1-wp
文章目录 SHCTF 2024 week1 wpMisc[Week1]真真假假?遮遮掩掩![Week1]拜师之旅①[Week1]Rasterizing Traffic[Week1]有WiFi干嘛不用呢? web[Week1] 单身十八年的手速[Week1] MD5 Master[Week1] ez_gittt[Week1] jvav[Week1] poppopop[Week1] 蛐蛐?蛐蛐! SHCTF 2024…...

docker-comapose安装部署mysql
docker-comapose安装部署mysql version: "3.4" services:mysql:image: docker.das-security.cn/middleware/mysql:8.4.1container_name: mysqlenvironment:- MYSQL_ROOT_PASSWORD密码volumes:- /etc/localtime:/etc/localtime- ./configs/mysql/initdb:/docker-entr…...

C语言初阶-数据类型和变量【下】
紧接上期------------------------->>>C语言初阶-数据类型和变量【上】 全局变量和局部变量在内存中存储在哪⾥呢? ⼀般我们在学习C/C语⾔的时候,我们会关注内存中的三个区域: 栈区 、 堆区 、 静态区 。 内存的分配情况 局部变量是…...

C++:命名空间(namespace)详细介绍与案例
命名空间(namespace)是C中的一个重要概念,用于组织代码和避免名称冲突。它们允许程序员将标识符(如变量、函数、类等)组织在一起,以便在较大的程序中防止命名冲突。 1. 基本概念 命名空间的基本定义方式如…...

专题十一_递归_回溯_剪枝_综合练习_算法专题详细总结
目录 1. 找出所有⼦集的异或总和再求和(easy) 解析: 方法一: 解法二: 总结: 2. 全排列 Ⅱ(medium) 解析: 解法一:只关心“不合法”的分支 解法二&…...

java中Runnable接口是什么?基本概念、工作原理、优点、`Runnable`与`Thread`的对比、与`Callable`接口的对比、实际场景
Runnable接口是Java提供的一种用于实现多线程的接口,通常用来定义任务的具体逻辑。与Thread类不同,Runnable接口只提供一种抽象方法run(),没有任何与线程的生命周期、管理相关的功能。它的主要作用是与Thread类或线程池(如Executo…...

Mybatis Plus连接使用ClickHouse也如此简单
通过阅读列式数据库ClickHouse官网,不难看出它有支持JDBC规范的驱动jar包,可以直接集成到Object Relational Mapping框架等,下面我用SpringBootMybatisPlus环境连接ClickHouse来演示一下 集成步骤 1.Maven引入ClickHouse提供的JDBC依赖 <…...

什么社交平台可以找到搭子?分享多款找搭子必备的人气软件
在这个丰富多彩的世界里,我们常常渴望有一个志同道合的搭子,一起分享生活的点滴,共同探索未知的领域。无论是追寻美食的舌尖之旅,还是踏上充满惊喜的旅途;无论是在健身房挥洒汗水…… 找到一个合适的搭子,都…...

STM32 RTC实时时钟 F407 寄存器
RTC介绍 STM32F1: RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。 即在F1系列,RTC的日历部分只有一个32位的寄存器 该寄存器直接存放 时间戳 的值,即࿱…...

矩阵等价、向量组等价、线性方程组同解与公共解的关系
矩阵等价 矩阵 A 、 B 等价 ⇔ 两矩阵秩相等 R ( A ) R ( B ) ⇔ 每个矩阵的行秩等于列秩,两个矩阵的行秩与列秩分别相等 ⇔ 若行满秩则列向量组等价 ⇔ 若列满秩则行向量组等价 \begin{align} 矩阵A、B等价\\ &\Leftrightarrow 两矩阵秩相等R(A)R(B)\\ &\…...