[C++]——红黑树(附源码)
目录
一、前言
二、正文
2.1 红黑树的概念
2.2 红黑树的性质
2.3红黑树节点的定义
2.4 红黑树的插入
2.4.1 情况一
2.4.2 情况二
编辑 2.4.3 情况三
2.5 红黑树的验证
三、全部代码
四、结语
一、前言
在上一篇博客中,为小伙伴们进行了AVL树的讲解,但是由于在实际场景中大部分插入的数据都是无序的,所以红黑树的应用相较于AVL树会更会广泛,插入相同的数据,红黑树的旋转次数会比AVL树少很多,且其层数也不会像二叉搜索树那样高。因此在本篇博客中为大家带来红黑树的讲解,如有不足之处,欢迎各位大佬们给予指正!
二、正文
2.1 红黑树的概念
红黑树,是一棵二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。
以下图为例我们发现最短的路径上有三个节点,最长的路径有4个节点,并没有超出最短路径的两倍。
2.2 红黑树的性质
在上面中我们了解到一颗红黑树中,最长路径的节点不超过最短路径的两倍,那么我们到底该如何让一颗二叉搜索树变成这样的一颗红黑树呢?这就需要满足红黑树的以下几个性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
2.3红黑树节点的定义
那么在了解完红黑树的概念及其性质后,接下来我们就来讲讲该如何实现这样的一颗红黑树。
首先我们要明确的是红黑树的底层结构其实是与AVL树是一样的,都是一颗搜索二叉树,且为了使他们的结构都能达到各自的平衡,因此都需要采取三叉链的结构,即树节点内必须包含父亲,左孩子和右孩子三个节点指针,以方便树的旋转平衡。除此之外,既然是红黑树,其节点就是有“颜色”的,那么理所应当的,我们在每个节点内还需要定义一个颜色,我们可以通过枚举的方式来实现,这也是其与AVL树不同的地方所在。
当然这里还有一个额外需要注意的地方,就是对于一个节点的初始化,其三叉链的节点指针好说,定义为空指针即可,但是颜色我们该定义为黑色还是红色呢?在这里我们采取的是红色,这里其实是考虑在尽量影响较少红黑树的结构下我们选择的,因为如果当我们将新插入节点的颜色定义为黑色时,那么该节点所处路径下的黑色节点数就都会加一,就会与其他路径的黑色节点数不同,在调整次数为各个路径黑色节点数相同就会比较麻烦;反之若是插入新节点的颜色为红色,那么就不会影响该路径的黑色节点数,倘若插入处的父亲节点为黑色,那么插入后仍为一颗红黑树。如果父亲节点为红色,虽然违背了红黑树“红色节点的左右孩子节点都是黑色”这一点,但是通过变色或者旋转的方式我们还是能够比较轻松将其重新变成一颗红黑树相较于去调整其他路径的黑色节点数来说,因此我们在创建一个新节点的时候,会将其颜色初始化为红色。
具体代码如下:
//枚举:红色和黑色
enum Color
{RED,BLACK
};//红黑树节点的定义
template <class K,class V>
struct RBTreeNode
{//采取三叉链的方式方便树的旋转平衡RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;//颜色Color _col;pair<K, V> _kv;RBTreeNode(const pair<K ,V> kv):_left(nullptr), _right(nullptr), _parent(nullptr), _col(RED) //默认初始化为红色, _kv(kv){}
};
2.4 红黑树的插入
在成功创建完一个红色的新节点后,接下来的操作就是将这个新节点插入树中。
首先,第一步就是找到其应所处的位置。由于红黑树的底层结构是一颗二叉搜索树,因此我们只需要从根节点开始不断进行数值的比较,若是比插入节点的数值大就来到左子树;比插入的节点数据小,就来到右子树,直至找到空指针为止,那么该处就是新节点所应该插入的位置。要注意的是如果遇到插入的数据在比较时遇到相同时就应该退出来,无需插入。(无重复数据的红黑树)
第二步就是进行新节点与父亲节点的链接,若是父亲节点的数据大于新节点,就链接到其左子树,小于新节点,则链接到右子树。
第三步就是进行红黑树规则的判断,判断在插入该节点后是否仍满足一颗红黑树,若是不满足则需要进行相对应的调整,使其重新变为一颗红黑树,这也是其在插入过程中最为重要的一步。那么我们该如何判断在插入新节点后,此树是否仍为一颗红黑树呢,其实在上面新节点的颜色选择上已经点出了,由于我们插入新节点的颜色是红色,那么其违反的规则只有一条,就是“红色节点的左右子树必须都为黑色节点”,因此只要新节点的父亲节点为红色,就说明我们插入新节点后,此树就不再是一颗红黑树,需要我们对此树进行一个调整使其重新变成一颗红黑树。
代码框架如下:
bool Insert(const pair<K, V>& kv){//空树if (_root == nullptr){_root = new Node(kv);}//树不为空else{//寻找父亲结点Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else return false;}//插入新节点cur = new Node(kv);if (cur->_kv.first > parent->_kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//检测插入新节点后,红黑树的性质是否发生变化while (parent && parent->_col == RED){…… }}//无论进行怎样的处理 根结点都为黑_root->_col = BLACK;return true;}
当我们找好位置插入新节点后,若是父亲节点的颜色为黑色,自然满足红黑树的性质,不需要再继续调整;但是如果父亲节点的颜色为红色,那么就不满足红黑树的性质,我们就需要根据不同的情况进行调整,下面我们就对这几种情况进行逐一的讲解。
注:cur为当前节点,p为父亲节点,g为祖父节点,u为叔叔节点
2.4.1 情况一
cur为红,p为红,g为黑,u存在且为红
面对这种情况,我们只需要将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。在向上调调整的过程中我们可能会遇到这两种情况:
1.cur为红色,p为黑色——满足红黑树的性质,调整完毕
2.一直调整至根节点,即g为nullptr——无需继续向上调整,将根节点,即p节点调整为黑色,调整完毕
示意图及代码如下:
//情况一:uncle存在且为红->变色//父亲是祖父的左节点if (parent == grandfather->_left){Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//变色后继续向上传递cur = grandfather;parent = cur->_parent;}}//父亲是祖父的右节点else if (parent == grandfather->_right){Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//变色后继续向上传递cur = grandfather;parent = cur->_parent;}}
2.4.2 情况二
cur为红,p为红,g为黑,u不存在
面对这种情况情况,操作起来就不像情况一那么简单,情况一无需考虑cur,p,g三节点之间的相对位置,而情况二则需要根据三者之间的相对位置来进行不同的旋转,大致有四种旋转情况:左单旋,右单旋,左右双旋和右左双旋
具体旋转和变色如下:
2.4.3 情况三
cur为红,p为红,g为黑,u存在且为黑
面对这种情况,与情况二的操作类似,都是旋转加变色
具体旋转和变色见下:
虽然情况二和情况三中一种是存在u节点且为黑,一种不存在u节点,但我们发现在旋转和变色的过程u节点几乎没有参与其中,因此我们在实现的时候其实可以将这两种情况归为一种。
具体代码如下:
//旋转加变色while (parent && parent->_col == RED){Node* grandfather = parent->_parent;//父亲是祖父的左节点if (parent == grandfather->_left){Node* uncle = grandfather->_right;//情况二\三:uncle不存在或者uncle存在但颜色为黑->旋转加变色else if (uncle == nullptr || uncle->_col == BLACK){//孩子在父亲的左边->右单旋加变色// g // p //c if (cur == parent->_left){RotateR(grandfather);grandfather->_col = RED;parent->_col = BLACK;break;}//孩子在父亲的右边->左右单旋加变色// g // p // c else if (cur == parent->_right){RotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;break;}}}//父亲是祖父的右节点else if (parent == grandfather->_right){Node* uncle = grandfather->_left;//情况二\三:uncle不存在或者uncle存在但颜色为黑->旋转加变色else if (uncle == nullptr || uncle->_col == BLACK){//孩子在父亲的右边->左单旋加变色// g // p // c if (cur == parent->_right){RotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;break;}//孩子在父亲的左边->右左单旋加变色// g // p // c else if (cur == parent->_left){RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;break;}}}}
在红黑树的节点插入之后,为了方便建立起对插入过程的直观理解,下面为大家呈现两种节点插入方式所带来的效果。
方式一:升序(降序插入) 插入构建红黑树
方式二:随机插入构建红黑树
2.5 红黑树的验证
当我们按照代码所写构建完一颗红黑树之后,下一步就是对我们所搭建的红黑树进行验证才能保证我们的代码无误。对于红黑树来说验证主要分为两步:
1. 检测其是否满足二叉搜索树(中序遍历是否为有序序列),对于这一步来说与前面AVL的验证是相同的,笔者就不在这里做过多赘述,有需求的小伙伴可以移步到博主的上一篇文章【C++】——AVL树-CSDN博客
2. 检测其是否满足红黑树的性质:
①根节点是否为黑色
②红色节点的左右子树是否都为黑色节点
③每条路径的黑色节点数相同
具体代码如下:
// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测bool IsValidRBTRee(){//空树if (_root == nullptr) return true;//根结点为黑色if (_root->_col == RED) return false;//每条路径的黑色结点数相同int benmarch = 0;Node* root = _root; //基准值while (root){if (root->_col == BLACK) ++benmarch;root = root->_left;}_IsValidRBTRee(_root, 0, benmarch);}bool _IsValidRBTRee(Node* pRoot, size_t blackCount, size_t pathBlack){if (pRoot == nullptr && blackCount != pathBlack){return false;}else if (pRoot == nullptr && blackCount == pathBlack){return true;}if(pRoot->_col==BLACK){blackCount++;}if (pRoot->_col == RED && pRoot->_parent && pRoot->_parent->_col == RED){cout << pRoot->_kv.first << "出现连续的红节点" << endl;return false;}return _IsValidRBTRee(pRoot->_left,blackCount,pathBlack) && _IsValidRBTRee(pRoot->_right,blackCount,pathBlack);}
三、全部代码
#pragma once//枚举:红色和黑色
enum Color
{RED,BLACK
};//红黑树节点的定义
template <class K,class V>
struct RBTreeNode
{//采取三叉链的方式方便树的旋转平衡RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Color _col;pair<K, V> _kv;RBTreeNode(const pair<K ,V> kv):_left(nullptr), _right(nullptr), _parent(nullptr), _col(RED), _kv(kv){}
};template<class K,class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:RBTree() {}bool Insert(const pair<K, V>& kv){//空树if (_root == nullptr){_root = new Node(kv);}//树不为空else{//寻找父亲结点Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_kv.first > kv.first){parent = cur;cur = cur->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else return false;}//插入新节点cur = new Node(kv);if (cur->_kv.first > parent->_kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//旋转while (parent && parent->_col == RED){Node* grandfather = parent->_parent;//父亲是祖父的左节点if (parent == grandfather->_left){Node* uncle = grandfather->_right;//情况一:uncle存在且为红->变色if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//变色后继续向上传递cur = grandfather;parent = cur->_parent;}//情况二:uncle不存在或者uncle存在但颜色为黑->旋转加变色else if (uncle == nullptr || uncle->_col == BLACK){//孩子在父亲的左边->右单旋加变色// g // p //c if (cur == parent->_left){RotateR(grandfather);grandfather->_col = RED;parent->_col = BLACK;break;}//孩子在父亲的右边->左右单旋加变色// g // p // c else if (cur == parent->_right){RotateL(parent);RotateR(grandfather);cur->_col = BLACK;grandfather->_col = RED;break;}}}//父亲是祖父的右节点else if (parent == grandfather->_right){Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//变色后继续向上传递cur = grandfather;parent = cur->_parent;}//情况二\三:uncle不存在或者uncle存在但颜色为黑->旋转加变色else if (uncle == nullptr || uncle->_col == BLACK){//孩子在父亲的右边->左单旋加变色// g // p // c if (cur == parent->_right){RotateL(grandfather);grandfather->_col = RED;parent->_col = BLACK;break;}//孩子在父亲的左边->右左单旋加变色// g // p // c else if (cur == parent->_left){RotateR(parent);RotateL(grandfather);cur->_col = BLACK;grandfather->_col = RED;break;}}}}}//无论进行怎样的处理 根结点都为黑_root->_col = BLACK;return true;}// 检测红黑树中是否存在值为k的节点,存在返回该节点的地址,否则返回nullptrNode* Find(const K& k){_Find(_root);}// 获取红黑树最左侧节点Node* LeftMost(){_LeftMost(_root);}// 获取红黑树最右侧节点Node* RightMost(){_RightMost(_root);}// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测bool IsValidRBTRee(){//空树if (_root == nullptr) return true;//根结点为黑色if (_root->_col == RED) return false;//每条路径的黑色结点数相同int benmarch = 0;Node* root = _root; //基准值while (root){if (root->_col == BLACK) ++benmarch;root = root->_left;}_IsValidRBTRee(_root, 0, benmarch);}private:bool _IsValidRBTRee(Node* pRoot, size_t blackCount, size_t pathBlack){if (pRoot == nullptr && blackCount != pathBlack){return false;}else if (pRoot == nullptr && blackCount == pathBlack){return true;}if(pRoot->_col==BLACK){blackCount++;}if (pRoot->_col == RED && pRoot->_parent && pRoot->_parent->_col == RED){cout << pRoot->_kv.first << "出现连续的红节点" << endl;return false;}return _IsValidRBTRee(pRoot->_left,blackCount,pathBlack) && _IsValidRBTRee(pRoot->_right,blackCount,pathBlack);}// 左单旋void RotateL(Node * pParent){Node* grandparent = pParent->_parent;Node* cur = pParent->_right;Node* cur_left = cur->_left;//旋转相关结点if (cur_left) cur_left->_parent = pParent; //不为空pParent->_right = cur_left;cur->_left = pParent;pParent->_parent = cur;if (this->_root == pParent){this->_root = cur;cur->_parent = nullptr;}else if (grandparent->_left == pParent){grandparent->_left = cur;cur->_parent = grandparent;}else if (grandparent->_right == pParent){grandparent->_right = cur;cur->_parent = grandparent;}}// 右单旋void RotateR(Node * pParent){Node* grandparent = pParent->_parent;Node* cur = pParent->_left;Node* cur_right = cur->_right;//旋转相关节点pParent->_left = cur_right;if (cur_right) cur_right->_parent = pParent; //不为空cur->_right = pParent;pParent->_parent = cur;if (grandparent == nullptr){this->_root = cur;cur->_parent = nullptr;}else if (grandparent->_left == pParent){grandparent->_left = cur;cur->_parent = grandparent;}else if (grandparent->_right == pParent){grandparent->_right = cur;cur->_parent = grandparent;}}Node* _Find(Node* root,const K& k){if (root == nullptr) return nullptr;if (root->_kv.first > k) _Find(root->_left, k);else if (root->_kv.first < k) _Find(root->_right, k);else return root;}Node* _LeftMost(Node* root){if (root == _root) return root;else if (root->_left == nullptr) return root;else return _LeftMost(root->_left);}Node* _RightMost(Node* root){if (root == _root) return root;else if (root->_right == nullptr) return root;else return _RightMost(root->_right);}Node* _root=nullptr;
};void text()
{const int N = 10000;vector<pair<int,int>> v;v.reserve(N);srand(time(0));for (size_t i = 0; i < N; ++i){v.push_back(pair<int,int>(i,i));}RBTree<int, int> RBTree;for (const auto& e : v){RBTree.Insert(e);cout << e.first << ":" << RBTree.IsValidRBTRee()<<endl;}
}
四、结语
到此为止,关于红黑树树的讲解就告一段落了,至于其他的内容,小伙伴们敬请期待呀!
关注我 _麦麦_分享更多干货:_麦麦_-CSDN博客
大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下期见!
相关文章:
[C++]——红黑树(附源码)
目录 一、前言 二、正文 2.1 红黑树的概念 2.2 红黑树的性质 2.3红黑树节点的定义 2.4 红黑树的插入 2.4.1 情况一 2.4.2 情况二 编辑 2.4.3 情况三 2.5 红黑树的验证 三、全部代码 四、结语 一、前言 在上一篇博客中,为小伙伴们进行了AVL树的讲解&#…...
网络文件系统搭建
在CentOS7上搭建网络文件系统(NFS),并让客户端进行挂载,具体步骤如下: 1. 服务器端操作 安装NFS服务器软件包: 执行以下命令安装NFS服务: sudo yum install nfs-utils -y 启动并启用NFS服务&…...
基于vue、VantUI、django的程序设计
首先构建vue项目,构建项目点这里 安装 npm install axios axios简介 Axios 是一个基于 promise 的 HTTP 库,用于发起请求和接收响应,实现异步操作 基本使用 axios对象 请求响应拦截 在utils文件夹里新建ajax.js 创建一个axios对象并…...
京准电钟解读:NTP网络对时服务器助力厂区改造方案
京准电钟解读:NTP网络对时服务器助力厂区改造方案 京准电钟解读:NTP网络对时服务器助力厂区改造方案 1)系统概述 时钟系统可通过网络进行管理及时间校对,为厂区提供高精度、全天时、全天候 的授时服务,统一全厂各种系统…...
本地docker-compose仓库搭建以及推送docker镜像到仓库
前言 以下部分知识只适用于linux,不适合小白,请自行甄别执行 1.搭建 #参考 https://blog.csdn.net/u011535199/article/details/107457275 version: 3 services:registry:restart: alwaysimage: registry:2ports:- 5000:5000environment:#REGISTRY_HT…...
WPF+MVVM案例实战(八)- 自定义开关控件封装实现
文章目录 1、案例运行效果2、项目准备2、功能实现1、控件模板实现2、控件封装1、目录与文件创建2、各文件功能实现 3、开关界面与主窗体菜单实现1、开关界面实现2、主窗体菜单实现 4、源代码获取 1、案例运行效果 2、项目准备 打开项目 Wpf_Examples,新建ToggleBut…...
单机kafka性能需要高性能的硬件做支撑
一般来说,单机kafka在硬件支持的情况下,能支持每秒100万写入,如果硬件没有那么好的话(机械硬盘,容器内给内存8G, CPU也不是很好),就只能减少每秒的写入量,每秒写入5万都比较不错了。 如果强行每…...
Spark 的 Http Broadcast 和 Torrent Broadcast 广播实现类的对比
在 Apache Spark 中,广播机制用于高效地将小型只读数据分发到集群中的各个执行器(Executor)。Spark 中主要有两种不同的广播实现方式:Http Broadcast 和 Torrent Broadcast。这两种方式的核心目标都是将数据高效地分发给所有工作节…...
030_Subplot_In_Matlab中多图绘制之subplot函数
基于子图的多图方法 专业的论文中通常涉及到多个有逻辑关系的图拼接在一起,构成相互支持或者对照。所以很早之前,Matlab就有这个子图的函数subplot。 这个函数的基本语义有三类: 在图窗上划分出一个矩形区域建立一个坐标系,并指…...
免费云服务器有什么使用限制和注意事项?
在数字化时代,云计算已经成为许多企业和个人用户的重要工具。对于初创企业、开发者和学生来说,免费的云服务器提供了一个低成本的解决方案,使他们能够进行项目开发、学习和实验。但在使用过程中也存在一些限制和注意事项。以下是主要的使用限…...
3-ZYNQ 折腾记录 -PS_PL AXI Interfaces
Zynq UltraScale MPSoC集成了功能丰富的四核或双核Arm Cortex-A53 MPCore基于处理系统(Processing System, PS)和可编程逻辑(Programmable Logic, PL)的单一设备。 PS和PL可以使用多个接口和其他信号进行紧密或松散的耦合。这使设计人员能够有效地将用户创建的硬件加速器和其他…...
总结test
1.IO流 |-- 字节流操作任何类型文件|-- 字符流操作纯字符类文件|-- BIO 传统IO流,阻塞型的,也就是BIO,当执行IO流时,CPU只能等待执行完当前任务,才能去执行其他线程任务|-- NIO非阻塞型IO流,CPU可以同时执行…...
在 On hold 期刊 eLife 上发表一篇生信文章需要什么工作量?
生信碱移 科研圈动态 根据弗雷赛斯以及相关媒体最新消息,中科院一区TOP,著名生命科学期刊 eLife [IF: 6.4]已被科睿唯安官方 On hold! ▲ 官网截图。图片来源:https://mjl.clarivate.com/home eLife是一本专注于生物医学和生命科…...
使用Django框架开发企业级Web应用
💖 博客主页:瑕疵的CSDN主页 💻 Gitee主页:瑕疵的gitee主页 🚀 文章专栏:《热点资讯》 使用Django框架开发企业级Web应用 1 引言 2 Django简介 3 安装Python与Django 4 创建Django项目 5 设计应用结构 6 创…...
认识线程 — JavaEE
目录 认识线程(Thread) 1 线程是什么? 2 为什么要有线程 3 进程和线程的区别 区别一 区别二 区别三 区别四 4. Java的线程和操作系统线程的关系 认识线程(Thread) 1 线程是什么? 一个线程就是一个 "执行流"。…...
【C++单调栈】853. 车队|1678
本文涉及的基础知识点 C单调栈 LeetCode853. 车队 在一条单行道上,有 n 辆车开往同一目的地。目的地是几英里以外的 target 。 给定两个整数数组 position 和 speed ,长度都是 n ,其中 position[i] 是第 i 辆车的位置, speed[i…...
第十届文荣奖华丽开幕,郁葱以青春与努力绽放青年演员光芒
10月27日,第十届文荣奖在众人的期待中盛大开启,内地青年女演员郁葱受邀出席,作为国内颇具影响力的影视奖项,文荣奖一直以来都致力于发掘和表彰优秀的影视作品和青年影视人才,为影视行业的发展注入新的活力,…...
CMake 生成器表达式介绍
【写在前面】 生成器表达式在构建系统生成期间进行评估,以生成特定于每个构建配置的信息。它们的形式为 $<...>。例如: target_include_directories(tgt PRIVATE /opt/include/$<CXX_COMPILER_ID>) 这将扩展为 “/opt/include/GNU”、“/opt…...
ubuntu 20.04编译驱动报gcc-12 not found错误
最近在自己安装的Ubuntu 系统上编译自定义驱动,发现无法编译.ko,错误如下: 按照如下操作,发现可以解决,记录下,主要是Ubuntu缺少g-12的包 安装包以后发现可以正常编译...
docker sameersbn/bind dns服务器
1. 安装 #下载docker 镜像 docker pull sameersbn/bind#运行 53端口若被占用会启动失败 docker run --name dns -d --restartalways \ --publish 53:53/tcp \ --publish 53:53/udp \ --publish 10000:10000/tcp \ -v /etc/localtime:/etc/localtime \ -v /data/bind/:/data \…...
错误:无法推送一些引用到 ‘https://gitee.com/chek_kk/python-electron-app.git‘
这个错误提示说明在提交时某个文件的大小超过了 Gitee 仓库的单文件大小限制(100MB)。你需要从Git 历史中彻底移除这个大文件,否则无法推送到远程仓库。 解决步骤 1. 确认大文件信息 使用以下命令找出超过限制的大文件: git re…...
深度剖析美区代理IP的多元应用与优势
在当今数字时代,代理IP(Proxy IP)已成为互联网使用中的一项关键技术。尤其在美区,代理IP在数据采集、网络安全及在线隐私保护等领域发挥着越来越重要的作用。本文将深入探讨代理IP的基本概念、应用场景以及它带来的诸多优势&#…...
基于KV260的基础视频链路通路(MIPI+Demosaic+VDMA)
目录 1. 简介 1.1 要点 1.2 背景 1.2.1 Got stuck 1.2.2 Cant be Initialized 2. Overlay 2.1 参考 Overlay 2.1.1 KV260 Base 2.1.2 Pynq-CV-OV5640 2.2 自建 Overlay 2.2.1 IIC IP 2.2.2 MIPI CSI-2 Rx 2.2.3 AXI4-S Subset 2.2.4 Demosaic 2.2.5 Pixel Pack …...
Uni-App-04
主页开发 保存主页数据 <script> import { indexData, base } from /serviceexport default {data() {return {base, //把服务器基础地址变量设置为数据属性carousels:[], //轮播广告条目列表menuItems:[], //当前用户选中的功能菜单列表activities:[], //最新的…...
ElasticSearch分片
本文内容参考了田雪松老师编著的《Elastic Stack应用宝典》 ElasticSearch作为一个搜索引擎,会存储海量的数据。而存储海量的数据,就要解决如何存储的问题,并且保证数据不会丢失,同时还需要保证数据检索的效率,尽可能…...
spring高手之路
以下是一些可以快速入门Spring的方法: 1. 学习基础知识 阅读官方文档:Spring官方文档是最权威的学习资料。它详细介绍了Spring的各个模块、概念和使用方法。从核心模块开始,了解如依赖注入(DI)和控制反转(…...
工字钢与H型钢有什么区别?90%的工程师都搞错了!
这里为大家做一个详尽的解答:很多人认为工字钢是国内的叫法,H型钢是国外的叫法,其实这个认知是错误的。H型钢和工字钢从形状上来说是不一样的,见下图: 工字钢 工字钢主要分为普通工字钢、轻型工字钢和宽翼缘工字钢。按…...
10个程序员可以接私活的平台(非常详细)零基础入门到精通,收藏这篇就够了
私活接的好收入不比上班少,一些同学靠接私活月收入也上万甚至几万了。今天老韩来分享一下有哪些接私活的网站和平台,转发收藏以后备用 我们先来聊聊什么样的私活不能接。。 1、没有第三方担保的个人对个人的尽量不要接,双方都没保障&#x…...
小程序云开发CMS新版数据模型讲解,可视化网页管理后台,内容管理对数据库进行增删改查操作,新闻小程序实战学习
一直跟着石头哥学习小程序开发的同学比较清楚cms是什么,cms就是可以进行可视化的管理云开发数据库的网页后台。有了cms我们可以很方便的管理云开发数据库。 但是云开发官方一直改版,所以现在cms功能被整合到了云开发的数据模型里,也就是现在想…...
undertow服务器初始化
springboot整合undertow服务器的源码从老生常谈的createWebServer方法谈起。spring会在生成所有bean后到创建web容器,此时会到容器找到ServletWebServerFactory接口bean,spring会根据引入的框架确定生成的ServletWebServerFactory,我们在mave…...
搞好姓氏源流网站建设/搜索引擎营销的主要方法
1. 在widget类中自动定义了bool event函数,这个函数默认会记录所有的操作类型,并且可以通过event->type进行调用;2. 所有的控件默认都有eventfilter()函数和installEventfilter()函数,控件可以直接调用,如果需要对eventfilter函…...
78建筑挂靠/windows优化大师收费吗
抽象类描述的是一个什么东西,属性。 抽象类是对类的抽象,描述是什么 抽象类,继承后重写接口描述的是他做什么,行为。接口是对行为的抽象,描述做什么 ,进行继承后实行接口 转载于:https://www.cnblogs.com…...
网站制作案例怎么样/腾讯搜索引擎入口
【jzoj 4743 NOIP2016 提高 A 组模拟 9.2】积木(Standard IO)Time Limits: 1000 ms $ \quad $ Memory Limits: 262144 KB $ \quad $ Detailed LimitsDescription Input 第一行包含一个整数 $ n $ 。 接下来 $ n $ 行,每行包含三个整数 $ a,b,c $ ,表示该…...
渝中网站建设/百度文库首页
文章目录(1)__int8、__int16、__int32、__int64(2)int8_t、uint8_t、int16_t、 uint16_t、int32_t、 uint32_t、int64_t、uint64_t(1)__int8、__int16、__int32、__int64 __int8、__int16、__int32、__int…...
网站返回503的含义是/东莞网站建设公司
1.Cassandra是一套开源分布式NoSQL数据库系统。它最初由Facebook开发并在2008年开源,用于储存收件箱等简单格式数据, 1.随着云时代的到来,与下一代云应用相关的许多挑战都集中在数据量和数据处理速度上,Cassandra可以轻松解决这一…...
丽水网站建设报价/百度广告客服电话
目录 HMR是什么 使用场景 配置使用HMR 配置webpack解析webpack打包后的文件内容配置HMRHMR原理 debug服务端源码 服务端简易实现服务端调试阶段 debug客户端源码 客户端简易实现客户端调试阶段问题总结 HMR是什么 HMR即Hot Module Replacement是指当你对代码修改并保存后&…...