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

武汉今日头条最新消息杭州seo网站排名

武汉今日头条最新消息,杭州seo网站排名,南昌网站建设制作公司,云服务器ecs是什么⭐上篇文章:35.C二叉树进阶4(平衡二叉搜索树 - AVL树及其旋转操作图解)-CSDN博客 ⭐本篇代码:c学习/19.map和set的使用用与模拟 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) ⭐标⭐是比较重要的部分 一. 什么是红…

⭐上篇文章:35.C++二叉树进阶4(平衡二叉搜索树 - AVL树及其旋转操作图解)-CSDN博客

⭐本篇代码:c++学习/19.map和set的使用用与模拟 · 橘子真甜/c++-learning-of-yzc - 码云 - 开源中国 (gitee.com)

⭐标⭐是比较重要的部分

 一. 什么是红黑树?

        红黑树也是一种二叉搜索树,红黑树中的节点有红色与黑色,通过控制节点的颜色来保证最长路径节点数不会超过最短路径节点数的2倍。从而保证该二叉搜索树是非常接近平衡的。

4.1 红黑树的性质

1 根节点是黑色的

2 每一条路径上的黑色节点数量相同

3 红色节点的孩子只能为黑色节点(无连续的红色节点)

4 叶子节点是黑色的(这里的叶子指的是最后的空节点)

        通过上面的性质可以总结出来:

每条路径黑色节点数量相同

最短路径为:全部是黑色节点                                                ​​​​​​​        ​​​​​​​        ​​​​​​​        

最长路径为:一红一黑

        这样就能保证最长路径不会最短路径的二倍,从而保证红黑树是近似平衡的。

二. 有AVL树为何还要红黑树?

        AVL树通过平衡因子和旋转操作来保证整棵树是高度平衡的,可以解决二叉搜索树退化为链表的问题。保证其增删查改效率为O(log N)。

        而红黑树通过控制节点颜色来保证整棵树是近似平衡的(最长路径不超过最短路径二倍),能够保证其增删查改的效率为O(log N) ~ 2*O(log N)

        既然如此,为何还要红黑树呢?

1 红黑树的平均效率是比AVL较低,但是现代计算机CPU效率非常高,logN和2 *log N的差异不是很大

2 AVL树严格的平衡是需要不断的旋转操作得到的,旋转操作是比较耗时的。而红黑树的旋转操作比AVL树少得多。

        所以在很多情况下,红黑树的效率更高,综合性能更好,且实现简单。

 三. 红黑树的代码框架  

3.1 红黑树的节点   

         红黑树节点只需增加一个表示颜色的变量即可

enum  Color
{RED,Block
};template<class K,class V>
struct rbTreeNode
{rbTreeNode<K, V>* _left;rbTreeNode<K, V>* _right;rbTreeNode<K, V>* _parent;pair<K, V> _kv;Color col;rbTreeNode(const pair<K, V>& _kv = pair<K, V>()):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED){}
};

        这里默认将节点设置为红色,因为红色节点更温和,插入新节点容易调整红黑树。如果默认节点是黑色,每一次插入数据都要调整各个路径的值,操作复杂。

3.2 红黑树框架

template<class K,class V>
class RBTree
{using Node = rbTreeNode<K, V>;
public:bool Insert(const pair<K, V>& kv){}bool Find(const pair<K, V>& kv){}
private:Node* _root;
};

如果想要增加其他功能,可以直接在类内部增加。本文主要说明红黑树的节点的插入。

四. 红黑树节点的插入操作⭐

        首先安装二叉搜索树的性质进行插入数据,插入数据后再根据红黑树的性质进行调整

3.1 插入节点父亲为黑色(情况一)

        如果插入节点的父亲为黑色,插入节点为红色。直接插入即可,无论是其左孩子还是右孩子。这样不会破坏红黑树的任意一个条件。

3.2 插入节点父亲为红色

        由于父亲为红色,插入节点也为红色。破坏了红黑树的条件(红色节点的孩子必须为黑色)。此时就需要进行调整。这里有很多种情况,读者可以根据图解快速理解。

        注意:

1 如果父亲为红色,那么爷爷一定是黑色

2 所以红黑树的调整主要是:叔叔节点的颜色,位置(爷爷的左右孩子),是否存在

a 叔叔存在且颜色为红色(情况二与三)

        如果叔叔存在且为红色,则会有下面两种情况。

        上面这两种情况,我们只需要将父亲p和叔叔u变为黑色,然后将爷爷变为黑色。这样就能保证从爷爷开始的整颗树满足红黑树

如下图:

 

调整完之后,还要继续向上调整。

        如果爷爷是根节点,则直接将爷爷变为黑色,调整结束。否则需要继续向上调整,因为爷爷是红色节点,如果爷爷的父亲是红色则需要重新调整(不能有连续的红节点)。

        此时爷爷g就是新的cur。 

就像下图:

 

b 叔叔不存在或者叔叔是黑色节点(情况三与四)

        图解如下:解释在图解中

         所以这种只需要对g进行右旋转然后再让p变黑色,g变红色即可

        如果cur此时是父亲的右侧,则需要先对p进行左旋。如下图:

 

        上面展示的是cur父亲是cur爷爷左孩子的情况,对于右孩子的情况也是一样。只是旋转的方向改一改就行。

c 插入操作的代码

	bool Insert(const pair<K, V>& kv){//1.按照搜索树的规则进行插入if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;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 (cur->_kv.first > parent->_kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;//2.调整颜色//新增结点是红色的(因为红色节更温和,影响红黑树的结构小)cur->_col = RED;while (parent && parent->_col == RED){Node* grandfather = parent->_parent;//父亲在祖父左边if (parent == grandfather->_left){//红黑树的调节关键看叔叔Node* uncle = grandfather->_right;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;//继续向上调整cur = grandfather;parent = grandfather->_parent;}else{//情况二三,叔叔是黑色或者不存在//情况三,cur在parent右边(折线),此时对parent左旋,再对grandfather右旋if (parent->_right == cur){RotateLeft(parent);swap(parent, cur);	//只是交换了指针,kv节点并没有交换(更换了父亲和孩子的位置)}//情况二,cur在parent左边(直线),此时对grandfather右旋即可//再让parent变黑,grandfather变红RotateRight(grandfather);parent->_col = BLACK;grandfather->_col = RED;break;}}else  //说明父亲在祖父的右边{Node* uncle = grandfather->_left;//情况一if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = grandfather->_parent;}else{//情况二三//情况三(折线),此时父亲在右边,cur在父亲左边,对parent右旋,再对grandfath左旋if (cur == parent->_left){RotateRight(parent);swap(cur, parent);}//情况二(直线)						RotateLeft(grandfather);grandfather->_col = RED;parent->_col = BLACK;break;	//此时颜色已经调整好了,不需要继续调整}}}_root->_col = BLACK;	//无论如何变色,最后让根为黑色。就不会出错return true;}

旋转操作的代码:

void RotateLeft(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;//要旋转节点的父亲Node* SubR = parent->_right;//要旋转节点的右孩子Node* SubRLeft = SubR->_left;//要旋转节点右孩子的左孩子//一:调整节点parent->_right = SubRLeft;if (SubRLeft)SubRLeft->_parent = parent;SubR->_left = parent;parent->_parent = SubR;//1.parent是根,现在SubR是根//2.parent是整棵树的子树,找到其父亲,旋转完成后,让subR与其父亲相连接if (_root == parent){_root = SubR;SubR->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubR;}else{ppNode->_right = SubR;}SubR->_parent = ppNode;}}//左左,右单旋void RotateRight(Node* parent){if (!parent)return;Node* ppNode = parent->_parent;Node* SubL = parent->_left;Node* SubLRight = SubL->_right;//1.旋转,调整节点parent->_left = SubLRight;if (SubLRight)SubLRight->_parent = parent;SubL->_right = parent;parent->_parent = SubL;if (_root == parent){_root = SubL;SubL->_parent = nullptr;}else{if (ppNode->_left == parent){ppNode->_left = SubL;}else{ppNode->_right = SubL;}SubL->_parent = ppNode;}}

 其他操作的代码在代码仓库中,读者可自行阅读。

五. 红黑树的应用

        很多软件,代码库都有着红黑树的身影。

1 C++STL中的map/set使用的就是红黑树

2 在某些代码库中,哈希表的链表过长时候会使用红黑树替代

3 某些数据库系统使用红黑树作为索引

4 Linux内核调度器,虚拟内存管理使用红黑树

......

http://www.dtcms.com/wzjs/137356.html

相关文章:

  • 大型电子商务网站建设方案seo站长工具下载
  • 网站建站哪个好网站推广开户
  • 网站设计制造seo包括什么
  • 飞机代理ip免费链接网站关键词优化报价
  • 毕节建设公司网站广告网站留电话
  • 做静态网站怎样让图片自己切换啥都能看的浏览器
  • 哪个网站可以做免费商业推广搜索图片
  • 怎样做网站建设的程序宁波优化系统
  • 国内最大的开源网站企业营销推广方案
  • 网站建设哪些网站可以网站的排名优化怎么做
  • 17网站一起做网店 新塘网站建设的一般步骤
  • b2c网站代表产品推广文案100字
  • 注册小规模公司需要什么资料seo综合查询怎么进入网站
  • 常州网站建设价格百度seo策略
  • o2o网站做推广公司百度信息流平台
  • 网站建设具体需求域名ip查询
  • 上海中高端网站建设郑州seo顾问
  • 有多少收费网站中国2022年重大新闻
  • 青岛网站建设王道下拉??百度网盘官网登录入口
  • 网站免费正能量软件下载seo优化一般包括哪些内容()
  • org做后缀的网站方象科技服务案例
  • 建设银行无锡分行网站it培训机构排名
  • 动易政府网站模板打开百度一下网页版
  • 织梦做单页面网站网络营销效果评估
  • 自助建站系统 破解可口可乐搜索引擎营销案例
  • 旅游网站规划设计与建设国内十大软件培训机构
  • 自己做的网站 jen郑州网站优化哪家好
  • 西安网站建设联系电话在线推广企业网站的方法有哪些
  • php+mysql网站开发社群营销策略有哪些
  • 阿里云服务器建设网站选择那个镜像南京网站推广公司