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

后台管理网站模板莱芜金点子最新招聘信息招聘网

后台管理网站模板,莱芜金点子最新招聘信息招聘网,自己建个网站怎么挣钱,网站优化关键词排名怎么做一、红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍&#xff0…

一、红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍,因而是接近平衡的。
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍,因而是接近平衡的。

红黑树的性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的 
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的 (即不能出现两个连续的红色结点)
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径(从根节点到空结点)上,均包含相同数目的黑色结点 
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点,也被叫做NIL)

下图是一个红黑树

根据红黑树的性质:我们能得到这样一个结论---最长路径不会超过最短路径的两倍,为什么呢?

理由如下:因为每条路径上黑色节点的个数要相同,所以最短的路径上的点均为黑色结点,同时因为不能出现红色结点相邻的情况,所以最长路径上的结点颜色只能是黑红相间,故得出上诉结论

二、红黑树结点定义

enum Colour //这里用的枚举类型,也可以用其他的类型,只要能代表红黑两种颜色就行,如true/false
{BLACK,RED
};template<class K,class V>
struct RBTreeNode {RBTreeNode* _left;RBTreeNode* _right;RBTreeNode* _parent;pair<K, V>_kv;Colour _col;RBTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED){}
};

思考:为什么要将结点颜色默认设置为红色???

理由如下:由于每条路径上的黑色节点的个数要保持相同,如果我们插入的结点的颜色为黑色,那么必然该节点所在路径的黑色节点的个数要增加,就会导致这颗树的其他所有路径都需要多一个黑色节点,影响范围太大,而如果插入的结点颜色为红色,我们只要关心它所在子树的情况就行,具体看下面的插入操作。故每个新插入结点颜色都默认为红色

三、红黑树插入结点

红黑树是在二叉搜索树的基础上加上其平衡限制条件,因此红黑树的插入可分为两步:
1.按照二叉搜索树的规则插入新节点,如下
template <class K,class V>
class RBTree 
{typedef RBTreeNode<K, V> Node;
public:bool insert(const pair<K,V>&kv){if (_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->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);cur->_parent = parent;if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}//调整红黑树//...}
private:Node* _root = nullptr;
};

2.检查新节点插入后,红黑树的性质有没有被破坏

因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何
性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连
在一起的红色节点,此时需要对红黑树分情况来讨论  (p-parent  g-grandfather  u-uncle)   

情况一:cur为红,p为红,g为黑,u存在且为红

在这种情况下,我们只要改变结点的颜色就能保持红黑树的性质。

(注意:这种情况下,不用关心cur所在的位置)

情况二:cur为红,p为红,g为黑,u不存在或为黑色

 

这里就无法通过改变p、g、u的颜色来保持红黑树的性质(读者可以去手玩尝试一下),需要进行旋转+变色才行,那么看到这种形状的图形,我们就应该想到AVL树中的单旋和双旋,上面的情况很明显对应右单旋,旋转之后如下图

如何改变颜色使得红黑树的性质保持不变?

1.uncle为空,显而易见,将g变为红,p变为黑(可能有人会觉得将cur变成黑不是也行嘛?但如果p为红,且它是子树,那么还需要向上调整,会很麻烦,但如果p为黑色,那么它本身既符合红黑树性质,也并不会对其他的子树产生影响,直接就一步到位了)

2.uncle为黑色,(这种情况下,cur不可能是新插入的结点,只能是情况一向上调整得到的),这里就要分析a,b,c,d,e这几颗子树中黑色节点的个数,显然a,b,c的黑色结点个数相同,d和e的黑色结点比abc少一个,所以将p变为黑色,g变为红色,就能保持红黑树的性质(至于为什么不选择将g变成红色,理由同上)

具体的旋转和AVL树一样,只是红黑树旋转后需要变色,AVL树旋转后需要调整平衡因子,不了解的,可以看我写过的AVL树

这里,我们还要考虑cur所在的位置,共四种情况,第一种情况就是上面所讲的,剩下三种的旋转+变色,留给读者思考【旋转不会的可以去看我之前写的AVL树】

 

总结:红黑树的结点的插入首先看父节点是否为黑色(插入结点为根的情况要特别判断),如果为黑,不用处理,如果为红,关键看uncle结点,它决定了我们是否需要旋转,如果是红色,则只需要变色,如果是黑色/不存在,我们需要根据cur所在的位置选择合适的旋转方式,并对旋转之后的结点进行变色

 代码如下---附带检查检查红黑树是否正确的函数

enum Colour {BLACK,RED
};template<class K,class V>
struct RBTreeNode {RBTreeNode* _left;RBTreeNode* _right;RBTreeNode* _parent;pair<K, V>_kv;Colour _col;RBTreeNode(const pair<K, V>& kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED){}
};template <class K,class V>
class RBTree {typedef RBTreeNode<K, V> Node;
public:bool insert(const pair<K,V>&kv){if (_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->_left;}else if (cur->_kv.first < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv);cur->_parent = parent;if (parent->_kv.first > kv.first){parent->_left = cur;}else{parent->_right = cur;}//父节点为黑,不用处理//为红需要调整while (parent && parent->_col == RED){//    g//  p   u//cNode* grandparent = parent->_parent;if (grandparent->_left == parent){Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED)//情况一{grandparent->_col = RED;parent->_col = uncle->_col = BLACK;cur = grandparent;parent = cur->_parent;}else//情况二{if (parent->_left == cur)//单旋{RotateR(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else//双旋{RotateL(parent);RotateR(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}else{//     g//  u     p//       c  cNode* uncle = grandparent->_left;if (uncle && uncle->_col == RED){//变色grandparent->_col = RED;parent->_col = uncle->_col = BLACK;//向上走cur = grandparent;parent = cur->_parent;}else{if (parent->_right == cur){RotateL(grandparent);parent->_col = BLACK;grandparent->_col = RED;}else{RotateR(parent);RotateL(grandparent);cur->_col = BLACK;grandparent->_col = RED;}break;}}}_root->_col = BLACK;return true;}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;Node* pParent = parent->_parent;subR->_left = parent;parent->_right = subRL;parent->_parent = subR;if (subRL)//注意h==0的情况subRL->_parent = parent;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{subR->_parent = pParent;if (pParent->_left == parent){pParent->_left = subR;}else{pParent->_right = subR;}}}void RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;Node* pParent = parent->_parent;subL->_right = parent;parent->_left = subLR;parent->_parent = subL;if (subLR)//注意h==0的情况subLR->_parent = parent;if (_root == parent){_root = subL;subL->_parent = nullptr;}else{subL->_parent = pParent;if (pParent->_left == parent){pParent->_left = subL;}else{pParent->_right = subL;}}}void InOrder(){_InOrder(_root);}void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_kv.first << " ";_InOrder(root->_right);}bool Isbalance(){return _Isbalance(_root);}//检查是否出现两个连续的红色节点+是否路径上的黑色节点的个数是否相同bool check(Node* root,int blacknum){if (root == nullptr){cout << blacknum << " ";return true;}if (root->_col == RED && root->_parent->_col == RED)return false;if (root->_col == BLACK)blacknum++;return check(root->_left, blacknum) && check(root->_right, blacknum);}bool _Isbalance(Node* root){if (root == nullptr)return true;if (root->_col == RED){cout <<"出现两个连续的红色节点:"<< root->_kv.first << endl;return false;}return check(root->_left, 1) && check(root->_right, 1);}
private:Node* _root = nullptr;
};

http://www.yayakq.cn/news/350729/

相关文章:

  • wordpress网站数据owl WordPress主题
  • 专业网站建设策划html代码雨
  • 网站小功能傻瓜建网站
  • 做网页怎么建站点长沙的企业网站建设
  • 网站建设中企动力上海生产制造erp
  • 哪里网站备案方便快wordpress分类目录用别名
  • 企业网站颜色选择网站建设背景和目标
  • 建站平台营销手机移动开发技术
  • 阳光市往房和城乡规划建设局网站福建建设执业资格注册管理中心网站
  • 屏幕分辨率 网站开发西安互联网网站建设
  • 为什么推荐企业做网站微信云开发文档
  • 用360云盘做网站万户网络oa
  • 互联网网站开发html5html5登录界面完整代码
  • 在线教育网站开发时长wordpress 搜索自定义字段
  • 怎么做电视台网站做网站多少宽带够
  • 中国最好的建设网站上海公共招聘网下载
  • 网站meta 优化建议不显示修改的wordpress
  • 专业做网站建设 昆山英国公司注册
  • 淄博学校网站建设方案网站开发 前端 后端
  • 信阳做网站优化wordpress导入用户数据库
  • 传媒公司网站建设方案线上营销推广方案有哪些
  • 如何 做网站动漫制作专业要多少分
  • 做网站的流程视频教程网站右下角代码
  • 有没有人与动物做的电影网站装修设计比较好的网站
  • 龙海市住房和城乡建设局网站广东新闻联播回放
  • h5网站开发 源码杭州app定制开发
  • 青岛做网站定制招商网官网
  • 建设网站要什么手续做新网站怎样提交360
  • 宿迁网站建设案例wordpress彩带背景
  • 能自己做网站接业务吗漳州 网站设计