【C++篇】红黑树的实现
目录
前言:
一,红黑树的概念
1.1,红黑树的规则
1.2,红黑树的最长路径
1.3,红黑树的效率分析
二,红黑树的实现
2.1,红黑树的结构
2.2,红黑树的插入
2.2.1,大致过程
2.2.2,情况1:变色处理
2.2.3,情况2:单旋+变色
2.2.4,情况3:双旋+变色
2.3,红黑树插入代码的实现
2.4,红黑树的验证
三,整体代码
四,测试代码
前言:
本篇会用到上篇【AVL树的实现】中的旋转知识。
一,红黑树的概念
红黑树是一颗二叉搜索树,它的每一个节点增加一个存储为来表示节点的颜色。可以是红色或者黑色。它通过对从根开始到叶子节点的每条路径上各个节点颜色的约束,确保最长路径不会超过最短路径的2倍,从而实现平衡的。
1.1,红黑树的规则
1,每个节点不是红色就是黑色。
2,根节点是黑色的。
3,红色节点的两个孩子只能是 黑色节点或者是空节点。也就是说不能出现连续的红色节点
4,对于任意一个节点,从该节点开始,到叶子节点的所有路径上,均包含相同数量的黑色节点。
以上 都是红黑树,满足红黑树的规则。
1.2,红黑树的最长路径
1,由第四条规则可知,从根节点开始的每条路径上,黑色节点的数量相同。所以在极端场景下,一颗红黑树,它的最短路径就是节点全为黑色的路径。假设红黑树的每条路径黑色节点数量都为b,那么最短路径的节点数量为b.
2,由 第三条规则可知,一条路径上不能由连续的红色节点,最长路径是由一黑一红间隔组成的,所以最长路径为2*b。
3,而对于一颗红黑树,最长和最短路径不一定存在。我们可以得出对于任意一颗红黑树,它的任意 一条路径长度x都是,b<=x<=2*b.
1.3,红黑树的效率分析
假设N是红黑树节点的数量,h是最短路径的长度,最长路径不超过2*h
可以得到2^h-1<= N <= 2^(2*h)-1,推出h大致为logN,也就意味着红黑树的增删查该最坏走2*logN,时间复杂度O(logN).
二,红黑树的实现
2.1,红黑树的结构
enum color
{
Red,
Black
};template<class k,class v>
struct RBTreeNode
{
RBTreeNode(const pair<k,v>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
{}
RBTreeNode<k, v>* _left;
RBTreeNode<k, v>* _right;
RBTreeNode<k, v>* _parent;
pair<k, v> _kv;
color _col;
};template<class k,class v>
class RBTree
{
typedef RBTreeNode<k, v> Node;
public://...
private:
Node* _root=nullptr;
};
2.2,红黑树的插入
2.2.1,大致过程
1,插入一个值需要按照搜索树的规则进行插入,再判断插入后是否满足红黑树的规则。
2,如果是空树插入,新增节点就是黑色节点。如果是非空树插入,新增节点就必须是红色节点,因为如果插入黑色节点,就一定会破坏规则4,而插入红色节点是有可能会破坏规则3,而且对于规则3来说,解决方法比规则4的解决方法容易。
3,非空树插入后,如果父节点是黑色节点,则没有违反任何规则,插入结束。
4,非空树插入后,如果父节点是红色节点,则违反规则3,进一步分析。
2.2.2,情况1:变色处理
由上图可知,c为红,p为红,g为黑,u存在且为红。在这种情况下,我们需要将p和u变黑,g变红,g成为新的c,继续向上更新。
分析:
因为p和u都是红色的,g是黑色的。把p和u变黑,左边子树路径各增加一个黑色节点,g再变红,相当于g所在路径的黑色节点数量不变,同时解决了c和p连续红节点的问题。
需要继续往上跟新是因为g是红色,如果g的父亲还是红色,就需要继续处理;如果g的父亲是黑色,则处理结束;如果g是整棵树的根,再将g变成黑色即可。
2.2.3,情况2:单旋+变色
c为红,p为红,u不存在或者u存在且u为黑色。在这种情况下,就需要进行单旋+变色处理
分析:
u不存在时,c一定是新增节点。
u存在且为黑色时,c一定不是新增节点,是在c的子树中插入,符号情况1,经过情况1后,c被调整为红色的。
上图展示的是右单旋的场景,下面是根据右单旋,画出的左单旋大致图,与右单旋过程相似:
总结:经过单旋+变色后,我们可以看到p做了子树新的根,且p是黑色的,所以不管p的父亲是黑色的还是红色的,都满足红黑树的规则,所以此时,就不需要往上更新了。
2.2.4,情况3:双旋+变色
c为红,p为红,g为黑,u不存在或者u存在且为黑,u不存在,则c一定是新增结点,u存在且为黑,则 c一定不是新增,c之前是黑色的,是在c的子树中插入,符合情况1,变色将c从黑色变成红色,更新上来的。
上图展示的是左右双旋+变色,同样右左双旋类似:
同样经过双旋+变色后,c成为新的根,且c为黑色,所以也不需要继续向上更新了。
2.3,红黑树插入代码的实现
bool Insert(const pair<k, v>& kv)
{//插入根节点,color->Blackif (_root == nullptr){_root = new Node(kv);_root->_col = Black;return true;}//根据搜索树的规则查找插入位置Node* cur = _root;Node* parent = nullptr;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);cur->_col = Red;//与父亲节点连接好if (parent->_kv.first < kv.first)parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;//颜色处理+旋转while (parent&& parent->_col == Red){//gNode* grandfather = parent->_parent;if (parent == grandfather->_left){//p为g的左边// g// p uNode* uncle = grandfather->_right;//叔叔存在且为红,情况1if (uncle && uncle->_col == Red){//变色parent->_col = Black;uncle->_col = Black;grandfather->_col = Red;//继续向上处理cur = grandfather;parent = cur->_parent;}else{//情况2,3//叔叔不存在或者叔叔为黑//u为黑,则c之前是黑的//u不存在,则c是新插入的if (cur == parent->_left){//右单旋场景// g// p u// cRotateR(grandfather);//变色parent->_col = Black;grandfather->_col = Red;}else{//左右双旋场景// g// p u// cRotateL(parent);RotateR(grandfather);//变色cur->_col = Black;grandfather->_col = Red;}//不需要进行向上更新break;}}else{//p为g的右边// g// u pNode* uncle = grandfather->_left;if (uncle && uncle->_col == Red){//情况1//变色parent->_col = Black;uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = cur->_parent;}else{//情况2,3if (cur == parent->_right){//左单旋场景// g// u p// cRotateL(grandfather);//变色parent->_col = Black;grandfather->_col = Red;}else{//右左双旋场景// g// u p// cRotateR(parent);RotateL(grandfather);//变色cur->_col = Black;grandfather->_col = Red;}//不需要继续向上更新break;}}}//跟的颜色可能被调整为红色,最后一步改为黑色即可_root->_col = Black;return true;
}
//右单旋
void RotateR(Node* parent)
{Node* subL = parent->_left;Node* subLR = subL->_right;Node* pparent = parent->_parent;if (subLR)subLR->_parent = parent;parent->_left = subLR;subL->_right = parent;parent->_parent = subL;if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (pparent->_left == parent)pparent->_left = subL;elsepparent->_right = subL;subL->_parent = pparent;}
}
//左单旋
void RotateL(Node* parent)
{Node* subR = parent->_right;Node* subRL = subR->_left;Node* pparent = parent->_parent;parent->_right = subRL;if (subRL)subRL->_parent = parent;parent->_parent = subR;subR->_left = parent;if (parent == _root){_root = subR;_root->_parent = nullptr;}else{if (pparent->_left == parent)pparent->_left = subR;elsepparent->_right = subR;subR->_parent = pparent;}
}
2.4,红黑树的验证
我们只需验证形成的树是否满足红黑树的四条规则即可。
其中,规则1和规则 2可以直接检查。
对于规则3,我们可以进行前序遍历,遍历到一个节点,判断该节点的颜色,再判断它的两个孩子的颜色,这样做太麻烦了。我们可以反过来,遍历到一个节点,如果他是红色的,判断它的父亲节点是否为黑色。
对于规则4,我们可以先从根开始找到一条路径上黑色节点的个数refNum,再对整棵树进行前序遍历,用变量 blackNum记录黑色节点的个数,当遍历到空的时候,与refNum比较即可。
bool Check(Node* root, int BlackNum, int num)
{if (root == nullptr){if (BlackNum != num)return false;return true;}if (root->_col == Red && root->_parent->_col == Red)return false;if (root->_col == Black)BlackNum++;return Check(root->_left, BlackNum, num) && Check(root->_right, BlackNum, num);
}
//验证
bool isbalance()
{if (_root == nullptr)return true;if (_root->_col == Red)return false;int num = 0;Node* cur = _root;while (cur){if (cur->_col == Black)num++;cur = cur->_left;}return Check(_root, 0, num);
}
三,整体代码
enum color
{Red,Black
};template<class k,class v>
struct RBTreeNode
{RBTreeNode(const pair<k,v>& kv):_left(nullptr),_right(nullptr),_parent(nullptr),_kv(kv){}RBTreeNode<k, v>* _left;RBTreeNode<k, v>* _right;RBTreeNode<k, v>* _parent;pair<k, v> _kv;color _col;
};template<class k,class v>
class RBTree
{typedef RBTreeNode<k, v> Node;
public:bool Insert(const pair<k, v>& kv){//插入根节点,color->Blackif (_root == nullptr){_root = new Node(kv);_root->_col = Black;return true;}//根据搜索树的规则查找插入位置Node* cur = _root;Node* parent = nullptr;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);cur->_col = Red;//与父亲节点连接好if (parent->_kv.first < kv.first)parent->_right = cur;elseparent->_left = cur;cur->_parent = parent;//颜色处理+旋转while (parent&& parent->_col == Red){//gNode* grandfather = parent->_parent;if (parent == grandfather->_left){//p为g的左边// g// p uNode* uncle = grandfather->_right;//叔叔存在且为红,情况1if (uncle && uncle->_col == Red){//变色parent->_col = Black;uncle->_col = Black;grandfather->_col = Red;//继续向上处理cur = grandfather;parent = cur->_parent;}else{//情况2,3//叔叔不存在或者叔叔为黑//u为黑,则c之前是黑的//u不存在,则c是新插入的if (cur == parent->_left){//右单旋场景// g// p u// cRotateR(grandfather);//变色parent->_col = Black;grandfather->_col = Red;}else{//左右双旋场景// g// p u// cRotateL(parent);RotateR(grandfather);//变色cur->_col = Black;grandfather->_col = Red;}//不需要进行向上更新break;}}else{//p为g的右边// g// u pNode* uncle = grandfather->_left;if (uncle && uncle->_col == Red){//情况1//变色parent->_col = Black;uncle->_col = Black;grandfather->_col = Red;cur = grandfather;parent = cur->_parent;}else{//情况2,3if (cur == parent->_right){//左单旋场景// g// u p// cRotateL(grandfather);//变色parent->_col = Black;grandfather->_col = Red;}else{//右左双旋场景// g// u p// cRotateR(parent);RotateL(grandfather);//变色cur->_col = Black;grandfather->_col = Red;}//不需要继续向上更新break;}}}//跟的颜色可能被调整为红色,最后一步改为黑色即可_root->_col = Black;return true;}//右单旋void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;Node* pparent = parent->_parent;if (subLR)subLR->_parent = parent;parent->_left = subLR;subL->_right = parent;parent->_parent = subL;if (parent == _root){_root = subL;_root->_parent = nullptr;}else{if (pparent->_left == parent)pparent->_left = subL;elsepparent->_right = subL;subL->_parent = pparent;}}//左单旋void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;Node* pparent = parent->_parent;parent->_right = subRL;if (subRL)subRL->_parent = parent;parent->_parent = subR;subR->_left = parent;if (parent == _root){_root = subR;_root->_parent = nullptr;}else{if (pparent->_left == parent)pparent->_left = subR;elsepparent->_right = subR;subR->_parent = pparent;}}void Inorder(){_Inorder(_root);}int Height(){return _Height(_root);}int size(){return _size(_root);}Node* Find(const k& key){Node* cur = _root;while (cur){if (cur->_kv.first < key){cur = cur->_right;}else if (cur->_kv.first > key){cur = cur->_left;}else{return cur;}}return nullptr;}//验证bool isbalance(){if (_root == nullptr)return true;if (_root->_col == Red)return false;int num = 0;Node* cur = _root;while (cur){if (cur->_col == Black)num++;cur = cur->_left;}return Check(_root, 0, num);}
private:bool Check(Node* root, int BlackNum, int num){if (root == nullptr){if (BlackNum != num)return false;return true;}if (root->_col == Red && root->_parent->_col == Red)return false;if (root->_col == Black)BlackNum++;return Check(root->_left, BlackNum, num) && Check(root->_right, BlackNum, num);}int _size(Node* root){if (root == nullptr)return 0;return _size(root->_left) + _size(root->_right) + 1;}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;}void _Inorder(Node* root){if (root == nullptr)return;_Inorder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_Inorder(root->_right);}Node* _root=nullptr;
};
四,测试代码
void TestRBTree1()
{RBTree<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.isbalance() << endl;
}
int main()
{TestRBTree1();return 0;
}
相关文章:
【C++篇】红黑树的实现
目录 前言: 一,红黑树的概念 1.1,红黑树的规则 1.2,红黑树的最长路径 1.3,红黑树的效率分析 二,红黑树的实现 2.1,红黑树的结构 2.2,红黑树的插入 2.2.1,大致过程…...
Linux的常用命令(一)
目录 一、文件处理命令 1.文件处理命令ls 2.文件处理命令cd 3.文件处理命令pwd 4.文件处理命令touch 5.文件处理命令mkdir 6.文件处理命令cp 7.文件处理命令mv 8.文件处理命令rm 9.文件处理命令cat 10.文件处理命令more 11.文件处理命令head 12.文件处理命令tail …...
小米vela系统(基于开源nuttx内核)——如何使用信号量进行PV操作
如何使用信号量进行PV操作 前言信号量1. 信号量简介2. NuttX中信号量的创建与使用2.1 Nuttx信号量的初始化和销毁2.2 信号量的等待和发布 3. 信号量的实际应用:下载任务示例3.1 实际代码3.2 代码说明3.3 执行说明 4. 信号量的优势与应用场景5. 常见应用场景…...
(01)STM32—GPIO
1. GPIO简介 GPIO(General Purpose Input Output)通用输入输出端口。可配置为8种输入输出模式。引脚电平:0V~3.3V,部分引脚可容忍5V。输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时…...
浏览器输入http形式网址后自动跳转https解决方法
一、问题描述 使用浏览器 网上冲浪 时会遇到一个情况: 在浏览器中输入“http域名”后会自动变成“https 域名”的形式,此时“https 域名”的网站可能已停止对外提供服务了,这时会出现如下不友好的网页提示: 二、处理方法&#x…...
mybatis的多对一、一对多的用法
目录 1、使用VO聚合对象(可以解决这两种情况) 多对一: 一对多: 2、非聚合的多对一做法: 3、非聚合的一对多做法: 1、使用VO聚合对象(可以解决这两种情况) 当我需要多对一、一对…...
生产管理看板助力节能科技公司实现数据自动化管理
在节能科技公司的生产过程中,数据管理的自动化是提高生产效率和产品质量的关键。然而,许多公司在数据记录、展示、对比和存档方面仍面临诸多痛点,如产品检测数据无法自动记录、缺乏直观的产线状态展示、检测数据对比繁琐耗时,以及…...
网络科技有限公司网络设计
网络科技有限公司网络设计 摘要:伴随着信息科技发展,上网变得一件必不可少的事情,当然网络安全对我们也是越来越重要。像我们的传统网结构是无法为我们的上网提供一个安全的网络环境。锐雯网络科技有限公司就是以网络安全为基本的对网络惊醒…...
C++没有Y Combinator?使用 C++ 实现 Y Combinator(中英双语)
C 中并没有直接内置的 Y Combinator,但通过现代 C 特性(如 lambda 表达式 和 std::function),我们可以实现一个类似 Y Combinator 的功能。 下面我们来详细讲解如何在 C 中实现 Y Combinator。 使用 C 实现 Y Combinator 目标 …...
YOLOv10-1.1部分代码阅读笔记-loaders.py
loaders.py ultralytics\data\loaders.py 目录 loaders.py 1.所需的库和模块 2.class SourceTypes: 3.class LoadStreams: 4.class LoadScreenshots: 5.class LoadImagesAndVideos: 6.class LoadPilAndNumpy: 7.class LoadTensor: 8.def autocast_list(source…...
《戴森球计划》异地远程联机攻略
文章目录 前言1. 下载MOD2.配置cpolar内网穿透3. 主机开启联机3.1 玩家加入游戏 4. 配置固定的TCP端口5. 游玩体验 前言 《戴森球计划》不仅是一款融合了科幻冒险与经营管理元素的游戏,更是一个让玩家在浩瀚宇宙中尽情探索和创造的平台。在这个游戏中,你…...
【Linux跬步积累】—— 线程
🌏博客主页:PH_modest的博客主页 🚩当前专栏:Linux跬步积累 💌其他专栏: 🔴 每日一题 🟡 C跬步积累 🟢 C语言跬步积累 🌈座右铭:广积粮࿰…...
计算机网络 (46)简单网络管理协议SNMP
前言 简单网络管理协议(SNMP,Simple Network Management Protocol)是一种用于在计算机网络中管理网络节点的标准协议。 一、概述 SNMP是基于TCP/IP五层协议中的应用层协议,它使网络管理员能够管理网络效能,发现并解决网…...
模型 前景理论
系列文章 分享模型,了解更多👉 模型_思维模型目录。面对得失,人们更怕失,参考点定输赢。 1 前景理论的应用 1.1 前景理论在投资决策中的应用案例 假设一位投资者面临两个投资方案的选择: 方案A:投资一只…...
Android ScrollView嵌套X5WebView大片空白问题
scrollview嵌套后webview的高度不可控。留有大片空白。 注:官方不建议scrollview嵌套webview 最好让webview自身滚动 解决方案: act_news_detail_wv.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView webView, Str…...
频域增强通道注意力机制EFCAM模型详解及代码复现
背景与动机 在深度学习领域,如何有效处理时间序列数据一直是一个重要的研究方向。近年来, 频域分析技术 在时间序列处理中展现出了巨大潜力,特别是离散余弦变换(DCT)因其能够高效捕捉低频信息并避免高频噪声干扰而受到广泛关注。 FECAM模型的开发正是基于这一背景,旨在…...
[计算机网络]一. 计算机网络概论第一部分
作者申明:作者所有文章借助了各个渠道的图片视频以及资料,在此致谢。作者所有文章不用于盈利,只是用于个人学习。 1.0推荐动画 【网络】半小时看懂<计算机网络>_哔哩哔哩_bilibili 1.1计算机网络在信息时代的作用 在当今信息时代&…...
第十三章:数据库技术
文章目录: 一:基础 1.概念 2.特点 3.常见数据库品牌 4.数据库应⽤系统 4.1 C/S 4.2 B/S 5.数据模型的分类 6.名词解析 7.关系运算 二:Access 1.基础 2.操作 2.1 建立表 2.2 维护表 2.3 创建查询 2.4 创建窗体 2.5 创建报表…...
中等难度——python实现电子宠物和截图工具
import io # 文件处理 import nt # windows nt 库直接获取对应的磁盘空间 import time # 时间 import zlib # 加解密 import ctypes # 调用 import struct # 处理字节二进制 import base64 # 编解码 import threading # 线程 import tkinter as tk # tk from datetime…...
构建优雅、高效的 Nodejs 命令行工具 - Archons
目录 项目简介安装基本用法样例创建一个简单的命令行工具使用archons上下文创建进度条 最后 项目地址: https://github.com/noctisynth/archons Bug反馈或功能请求:https://github.com/noctisynth/archons/issues 项目简介 Archons意思是“执政官”,我使…...
源码编译安装httpd 2.4,提供系统服务管理脚本并测试
1.安装httpd wget https://downloads.apache.org/httpd/httpd-2.4.62.tar.gzbmcv tar -zxvf httpd-2.4.62.tar.gz cd httpd-2.4.62 2.安装依赖包 sudo yum install -y gcc make apr-devel apr-util-devel pcre-devel sudo yum groupinstall "Development Tools"…...
【爬虫】某某查cookie逆向
代码仅供技术人员进行学习和研究使用,请勿将其用于非法用途或以任何方式窃取第三方数据。使用该代码产生的所有风险均由用户自行承担,作者不对用户因使用该代码而造成的任何损失或损害承担任何责任。 加密参数 加密参数主要是cookie,其中只有…...
【华为路由/交换机的ssh远程设置】
华为路由/交换机的ssh远程设置 R1(client):10.1.1.1 R2(server):10.1.1.2 R2服务端配置: 生成本机密钥 查看生成的密钥 设置AAA授权验证方式,并设置支持SSH协议 创建本地用户&…...
Linux:System V - 共享内存
1.System V共享内存的原理 通过为用户提供系统调用接口,让用户可以申请一块空间,进程A/B也可以通过系统调用接口将创建好的内存通过页表映射进进程的地址空间。完成让不同的两个进程看见同一份资源的目的。如果未来不想继续通信,取消进程和内…...
闪豆多平台视频批量下载器
1. 视频链接获取与解析 首先,在哔哩哔哩网页中随意点击一个视频,比如你最近迷上了一个UP主的美食制作视频,想要下载下来慢慢学。点击视频后,复制视频页面的链接。复制完成后,不要急着关闭浏览器,因为接下来…...
《鸿蒙Next微内核:解锁人工智能决策树并行计算的加速密码》
在当今人工智能飞速发展的时代,提升运算速度是推动其进步的关键。鸿蒙Next以其独特的微内核特性,为设计决策树的并行计算框架提供了新的思路和契机。 鸿蒙Next微内核特性概述 鸿蒙Next的微内核架构将核心功能模块化,仅保留进程管理、内存管…...
AWS Lambda
AWS Lambda 是 Amazon Web Services(AWS)提供的无服务器计算服务,它让开发者能够运行代码而不需要管理服务器或基础设施。AWS Lambda 会自动处理代码的执行、扩展和计费,开发者只需关注编写和部署代码,而无需担心底层硬…...
Python入门教程丨2.3 流程控制、算法效率分析及优化
流程控制是用于控制程序执行顺序的机制,它决定了程序中的语句按照何种顺序被执行。 本节课将详细讲解 Python 流程控制的三大核心结构:顺序、条件和循环,并配备一些小案例。 1. 顺序结构:从头到尾依次执行 顺序结构是程序中最基…...
NVIDIA发布个人超算利器project digital,标志着ai元年的开启
上图NVIDIA公司创始人兼首席执行官 黄仁勋(Jensen Huang) 这些年被大家熟知的赛博朋克风格一直都是未来的代言词,可以承载人类记忆的芯片,甚至能独立思考的仿生人,现在,随着NVIDIA的project digital发布之后…...
spring-mvc源码分析v3.3.0
分析下springboot内嵌tomcat启动流程,即springboot-mvc <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>3.3.0</version> </dependency>环境…...
反爬风控设计之请求头顺序检测
本次主要讲解请求头的顺序检测的反爬实现, 如下使用Django写的headers请求头顺序检验算法: def index(request):# 获取请求头的顺序request_order list(request.META.keys())print(request_order)# 定义标准请求头顺序standard_order ["HTTP_HO…...
力扣 查找元素的位置
二分查找经典例题。 题目 要是只是从数组中用二分查找对应的元素,套一下模板一下就可以得出了,然后这题就在于其中会有多个目标元素,要用不同的方式在找到第一个元素时再做偏移。 时间复杂度:O(log n),空间复杂度&am…...
Android-V lmkd 中的那些属性值
源码基于:Android V 相关博文: Android lmkd 机制详解(一) Android lmkd 机制详解(二) Android lmkd 机制从R到T 1. 汇总 属性名说明默认值 ro.lmk.debug 启动 lmkd 的debug 模式,会打印一…...
LabVIEW 程序中的 R6025 错误
R6025错误 通常是 运行时库 错误,特别是与 C 运行时库 相关。这种错误通常会在程序运行时出现,尤其是在使用 C 编译的程序或依赖 C 运行时库的程序时。 可能的原因: 内存访问冲突: R6025 错误通常是由于程序在运行时访问无效内…...
vmware虚拟机配置ubuntu 18.04(20.04)静态IP地址
VMware版本 :VMware Workstation 17 Pro ubuntu版本:ubuntu-18.04.4-desktop-amd64 主机环境 win11 1. 修改 VMware虚拟网络编辑器 打开vmware,点击顶部的“编辑"菜单,打开 ”虚拟化网络编辑器“ 。 选择更改设置&#…...
mybatis延迟加载、缓存
目录 一、所需表 二、延迟加载 1.延迟加载概念 2.立即加载和延迟加载的应用场景 3.多对一延迟加载查询演示 (1)实体类 User Account (2)AccountMapper接口 (3)AccountMapper.xml (4)UserMapper接口 (5)UserMapper.xml (6)在总配置文件(mybatis-config.xml)中开启延…...
云上贵州多彩宝荣获仓颉社区先锋应用奖 | 助力数字政务新突破
在信息技术应用创新的浪潮中,仓颉社区吸引了众多企业和开发者的积极参与,已有多个应用成功落地,展现出蓬勃的创新活力。仓颉编程语言精心遴选了在社区建设、应用创新、开源共建、技术布道等方面做出突出贡献的优秀项目应用,并颁发…...
设计模式02:结构型设计模式之适配器模式使用情景及其基础Demo
1.适配器模式 用途:接口兼容评价:复杂、冗余、难以调试,个人认为直接在旧系统那里封装一个新实现调用旧实现就好了场景:系统A、B、C想调用同一个功能接口,但是实现细节存在差异时(其实就是入参和出参转化处…...
镭速大文件传输视频文件预览实现原理
镭速可以支持视频预览,在测试过程中需要大量不同格式的视频,如果直接去找各种格式的视频不太现实,所以就会用到一个视频格式转换的工具ffmpeg,本文将介绍ffmpeg的基本使用方法。FFmpeg 是一个免费开源的音视频处理工具,…...
Mac上安装Label Studio
在Mac上安装Anaconda并随后安装Label Studio,可以按照以下步骤进行: 1. 在Mac上安装Anaconda 首先,你需要从Anaconda的官方网站下载适用于Mac的安装程序。访问Anaconda官网,点击“Download Anaconda”按钮,选择适合M…...
git操作(Windows中GitHub)
使用git控制GitHub中的仓库版本,并在Windows桌面中创建与修改代码,与GitHub仓库进行同步。 创建自己的GitHub仓库 创建一个gen_code实验性仓库用来学习和验证git在Windows下的使用方法:https://github.com/Martianing/gen_code git初始设置…...
低代码平台:技术复杂性的系统简化
在传统开发模式下,应用构建需要经历需求分析、代码开发、测试部署等多环节,流程繁琐且耗时,往往成为企业技术创新的瓶颈。低代码平台通过模块化和自动化技术重新定义开发流程,使开发者能够在较短时间内实现复杂的应用功能…...
物联网网关Web服务器--lighttpd服务器部署与应用测试
以下是在国产ARM处理器E2000飞腾派开发板上部署 lighttpd 并进行 CGI 应用开发的步骤: 1、lighttpd简介 Lighttpd 是一款轻量级的开源 Web 服务器软件,具有以下特点和功能: 特点 轻量级:Lighttpd 在设计上注重轻量级和高效性&a…...
Flutter+vsCode 安装问题记录
VSCode在安装完AndroidSDK以及相关插件后,运行Flutter项目时选择模拟器提示:avdmanager is missing from the Android SDK,确保环境变量中存在ANDROID_HOME,且执行了flutter config --android-sdk 地址后,如果还提示&a…...
【CompletableFuture实战】
CompletableFuture实战 前言 前言 过去的一年,匆匆忙忙,换了一次工作,写博客的习惯就落下了,总之,有点懈怠。希望今年能重拾信心,步入正规! CompletableFuture的用法网上资料颇多,…...
【k8s面试题2025】3、练气中期
体内灵气的量和纯度在逐渐增加。 文章目录 在 Kubernetes 中自定义 Service端口报错常用控制器Kubernetes 中拉伸收缩副本失效设置节点容忍异常时间Deployment 控制器的升级和回滚日志收集资源监控监控 Docker将 Master 节点设置为可调度 在 Kubernetes 中自定义 Service端口报…...
【高可用自动化体系】自动化体系
架构设计的愿景就是高可用、高性能、高扩展、高效率。为了实现架构设计四高愿景,需要实现自动化系统目标: 标准化。 流程自助化。 可视化:可观测系统各项指标、包括全链路跟踪。 自动化:ci/cd 自动化部署。 精细化:…...
Spring boot框架下的RocketMQ消息中间件
1. RocketMQ 基础概念 1.1 核心概念 以下是 RocketMQ 核心概念在 Spring Boot 的 Java 后端代码中的实际使用方式: Producer(生产者) 定义:Producer 是负责发送消息到 RocketMQ 的组件。它可以将消息发送到指定的 Topic。 实…...
http转化为https生成自签名证书
背景 项目开发阶段前后交互采用http协议,演示环境采用htttps协议 ,此处为个人demo案例 组件 后端:springBoot 前端:vue web 服务:tomcat 部署环境:linux 生成自签名证书 创建目录 存储证书位置 # mkdir -p…...
关于2025年智能化招聘管理系统平台发展趋势
2025年,招聘管理领域正站在变革的十字路口,全新的技术浪潮与不断变化的职场生态相互碰撞,促使招聘管理系统成为重塑企业人才战略的关键力量。智能化招聘管理系统平台在这一背景下迅速崛起,其发展趋势不仅影响企业的招聘效率与质量…...