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

基于asp的医疗网站开发系统软件开发公司

基于asp的医疗网站开发,系统软件开发公司,wordpress文章显示会员阅读,wordpress默认管理员密码目录 引入 概念 红黑的的实现 插入实现 找节点插入位置 新节点的父节点是黑色 新节点的父节点是红色 uncle节点是红色 uncle不存在或是黑色 插入代码汇总 对树进行检查 引入 为了解决普通二叉搜索树的极端情况——退化为单支树,采用了平衡二叉搜索树&…

目录

引入

概念

红黑的的实现

插入实现

找节点插入位置

新节点的父节点是黑色

新节点的父节点是红色

uncle节点是红色

uncle不存在或是黑色

插入代码汇总

对树进行检查


引入

为了解决普通二叉搜索树的极端情况——退化为单支树,采用了平衡二叉搜索树,其中包含AVL树和红黑树,关于AVL树的剖析已经有详细介绍,本篇将会对红黑树进行深度剖析。

二叉搜索树-CSDN博客文章浏览阅读1k次,点赞29次,收藏16次。关于搜索二叉树的结构及原理的分析,对搜索二叉树的算法进行剖析,实现搜索二叉树的结构及功能,对部分函数使用递归的方法实现 https://blog.csdn.net/2401_87944878/article/details/146377883

概念

红黑树根据其名称可以得知:其节点是有颜色的,包含两种节点:红节点和黑节点。红黑树与AVL树异曲同工之妙,红黑树舍弃了AVL树的严格条件(每个节点的平衡因子绝对是不大于1),而使用节点的颜色取而代之。

AVL树剖析-CSDN博客文章浏览阅读975次,点赞34次,收藏28次。AVL树是二叉平衡搜索树的重要一部分,本文对AVL树的插入的实现进行深度剖析,帮助读者更好的理解和掌握AVL树的底层逻辑。 https://blog.csdn.net/2401_87944878/article/details/146506996

 红黑树保证不会出现普通二叉搜索树极端情况的方法是:让红黑树的最长路径不超过最短路径的二倍,实现近似平衡。而完成这一要求,就需要了解红黑树的插入规则。

红黑树条件:1)每一个节点颜色不是红色就是黑色;

2)根节点必须是黑色;

3)如果一个节点是红色,则其左右节点必须是黑色;

4)对于每一个节点,从该节点到其所有后代叶节点的路径上都包含相同数量的黑节点。

思考:为什么红黑树的条件可以保证红黑树的最长路径不超过最短路径的二倍???

根据红黑树规则的第四条:全是黑节点的路径是最短路径。

根据红黑树规则的第三条:任何路径上不会出现连续的红节点,所以最长路径是一红一黑连续的路径。

根据以上两个规则就完美实现了,红黑树最长路径不超过最短路径的两倍。

红黑树没有AVL树平衡,这也意味着每一次插入红黑树调整的次数更少效率更高。但是其没有AVL树平衡,也说明其深度可能更深(实际上也不会太深),搜索效率不如AVL树。

与AVL树严格控制平衡所付出的代价相比,红黑树深度的增加微乎其微。

AVL树剖析-CSDN博客文章浏览阅读975次,点赞34次,收藏28次。AVL树是二叉平衡搜索树的重要一部分,本文对AVL树的插入的实现进行深度剖析,帮助读者更好的理解和掌握AVL树的底层逻辑。 https://blog.csdn.net/2401_87944878/article/details/146506996


红黑的的实现

红黑树的节点存储内容:左右子树,父节点,颜色,数据。

enum Col
{RED,BLACK
};template<class K,class  V>
struct RBTreeNode
{//默认构造函数RBTreeNode(const pair<K, V>& kv):_kv(kv),_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED){ }pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Col _col;
};template<class K,class V>
class RBTree
{typedef RBTreeNode<K, V> Node;private:Node* _root=nullptr;
};

插入实现

红黑树的插入分两大类:1)根节点为空,插入黑色节点代替根节点;2)根节点不为空,创建红色节点,插入....

与AVL树插入显示也有三个步骤:1)找节点插入位置;2)判断是否需要调整;3)进行调整。

注意:在每次插入后,为防止根节点的颜色改变,需要将跟节点至为黑色。

找节点插入位置

找节点的方法与普通二叉树一样,在此不过多赘述了。

bool Insert(const pair<K, V> kv)
{Node* newnode = new Node(kv);if (_root == nullptr){_root = newnode;   //根节点为空,直接进行赋值_root->_col = BLACK;return true;}//根节点不为空,找节点插入位置Node* pcur = _root;Node* parent = nullptr;while (pcur){parent = pcur;if (pcur->_kv.first > kv.first){pcur = pcur->_left;}else if (pcur->_kv.first < kv.first){pcur = pcur->_right;}else{return false;   //相等不需要插入}}//找到节点的位置//进行插入if (parent->_kv.first > kv.first){parent->_left = newnode;}else{parent->_right = newnode;}newnode->_parent = parent;//检查节点是否满足要求//....}

新节点的父节点是黑色

新节点的父节点是黑色,插入成功,该节点满足条件,直接返回。

//检查节点是否满足要求
//....
//父节点是黑色,满足条件
if (parent->_col == BLACK)
{_root->_col = BLACK;return true;
}
else    //父节点是红色,此时出现连续的红色,需要进行调整
{}

新节点的父节点是红色

新节点是红色则会出现有两种情况,根据uncle(newnode->parent->parent->child:新节点的爷爷节点的另一个子节点)节点进行区分。

1)uncle节点存在且为红色;

2)uncle节点不存在或uncle节点存在且为黑色。

如果新节点的父节点是红色,此时就出现了连续的红色节点,此时需要对红黑树进行调整。

此处处理颜色的关键是:让节点变色或将来连续的红节点分开。

uncle节点是红色

此处统一以cur,parent在左数为例。

对与uncle存在且是红色的处理方法比较简单:将uncle和parent的颜色换成黑色,将grandparent颜色换成红色即可。既保证了cur节点的父节点不在是红色,还让grandparent所在的支树中黑色节点的个数不变。

注意:此处的grandparent如果有父节点,还需要对父节点进行判断,父节点是不是红色。

else    //父节点是红色,此时出现连续的红色,需要进行调整
{pcur = newnode;while (parent && parent->_col == RED){Node* grandparent = parent->_parent;if (parent == grandparent->_left)  //分类确定uncle节点{Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED){//对节点进行变色uncle->_col = parent->_col = BLACK;grandparent->_col = RED;pcur = grandparent;   //继续向上调整parent = pcur->_parent;}else   //uncle节点是空或uncle节点是黑色{ }}else  //parent=grandparent->_right{}}
}

uncle不存在或是黑色

当uncle节点不存在,或是黑色;仅仅变色已经解决不了问题了,此处与AVL树相似,也需要先进行旋转再变色。

关于旋转的具体细节可以看看《AVL树剖析》,此处就直接使用了。

通过旋转使得树的高度降低,跟趋近于平衡,通过变色让树重新成为红黑树。

当然旋转的情况和AVL树相同,也有四种情况:左旋,右旋,左右双旋,右左双旋。此处不再赘述,可移值《AVL树剖析》。

else   //uncle节点是空或uncle节点是黑色
{ //判断旋转方式//上述if条件中已经确定了parent==grandparent->_leftif (pcur == parent->_left){//以grandparent为中心,进行右旋RotateR(grandparent);//进行变色parent->_col = BLACK;grandparent->_col = RED;_root->_col = BLACK;//此处parent是当前子树的根且是黑色,不用继续向上调整了return true;}else   //cur==parent->_right{//需要进行双旋RotateL(parent);RotateR(grandparent);//调色pcur->_col = BLACK;grandparent->_col = parent->_col = RED;_root->_col = BLACK;return true;}
}

插入代码汇总

bool Insert(const pair<K, V> kv)
{Node* newnode = new Node(kv);if (_root == nullptr){_root = newnode;   //根节点为空,直接进行赋值_root->_col = BLACK;return true;}//根节点不为空,找节点插入位置Node* pcur = _root;Node* parent = nullptr;while (pcur){parent = pcur;if (pcur->_kv.first > kv.first){pcur = pcur->_left;}else if (pcur->_kv.first < kv.first){pcur = pcur->_right;}else{return false;   //相等不需要插入}}//找到节点的位置//进行插入if (parent->_kv.first > kv.first){parent->_left = newnode;}else{parent->_right = newnode;}newnode->_parent = parent;//检查节点是否满足要求//....//父节点是黑色,满足条件if (parent->_col == BLACK){_root->_col = BLACK;return true;}else    //父节点是红色,此时出现连续的红色,需要进行调整{pcur = newnode;while (parent && parent->_col == RED){Node* grandparent = parent->_parent;if (parent == grandparent->_left)  //分类确定uncle节点{Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED){//对节点进行变色uncle->_col = parent->_col = BLACK;grandparent->_col = RED;pcur = grandparent;   //继续向上调整parent = pcur->_parent;}else   //uncle节点是空或uncle节点是黑色{ //判断旋转方式//上述if条件中已经确定了parent==grandparent->_leftif (pcur == parent->_left){//以grandparent为中心,进行右旋RotateR(grandparent);//进行变色parent->_col = BLACK;grandparent->_col = RED;_root->_col = BLACK;//此处parent是当前子树的根且是黑色,不用继续向上调整了return true;}else   //cur==parent->_right{//需要进行双旋RotateL(parent);RotateR(grandparent);//调色pcur->_col = BLACK;grandparent->_col = parent->_col = RED;_root->_col = BLACK;return true;}}}else  //parent=grandparent->rigth{Node* uncle = grandparent->_left;if (uncle && uncle->_col == RED){//对节点进行变色uncle->_col = parent->_col = BLACK;grandparent->_col = RED;pcur = grandparent;   //继续向上调整parent = pcur->_parent;}else   //uncle节点是空或uncle节点是黑色{//判断旋转方式//上述if条件中已经确定了parent==grandparent->_rightif (pcur == parent->_right){//以grandparent为中心,进行右旋RotateL(grandparent);//进行变色parent->_col = BLACK;grandparent->_col = RED;//此处parent是当前子树的根且是黑色,不用继续向上调整了_root->_col = BLACK;return true;}else   //cur==parent->_left{//需要进行双旋RotateR(parent);RotateL(grandparent);//调色pcur->_col = BLACK;grandparent->_col = parent->_col = RED;_root->_col = BLACK;return true;}}}}}_root->_col = BLACK;return true;
}


对树进行检查

关于红黑树的检查主要检查:1)红节点是否连续;2)每条支路的黑节点个数是否相同。

1)如果一个节点是红节点,通过检查其父节点的颜色来确定是否有连续的红节点。

2)每条路的节点个数的检查:通过先遍历一条支路,统计黑色节点个数,再与其他支路比较。

	bool Isbance(){int num = 0;  //记录根到叶子节点有多少个黑节点Node* pcur = _root;while (pcur){if (pcur->_col == BLACK){++num;}pcur = pcur->_left;}return Isbance(_root,num,0);   //num是每条支路黑节点个数的参照}private:bool Isbance(Node* root,int num,int each)   //each记录当前之路黑节点个数{if (root == nullptr){if (each == num)  //每条路的黑色节点数相同return true;cout << "黑色节点个数不对" << endl;return false;}if (root->_col == BLACK){each++;}else{if (root->_parent->_col == RED)  //看父节点是不是红色{return false;cout << root->_kv.first << " 红节点连续" << endl;}}return Isbance(root->_left,num,each) && Isbance(root->_right,num,each);}
http://www.dtcms.com/wzjs/537794.html

相关文章:

  • 网站建设微分销响应式 企业网站
  • 免费的网站模版下载做门户网站那个系统好
  • 公司网站用什么程序网站域名备案
  • 怎么建立自己网站 asp阿里云iis放网站
  • 郑州陆港开发建设有限公司网站美术馆网站建设概述
  • 织梦网站上传数据库什么做电子书下载网站好
  • 专门看广告的网站铜陵公司做网站
  • 网站开发设计文员安徽网站开发与维护专业
  • 找人做的网站怎么运行网址是什么意思
  • 修改网站dns企业网站管理的含义及内容
  • 牛天下网站建设沈阳公司建设网站
  • 深圳做微信网站接帮人家做网站的网站
  • 丹阳高铁站对面的规划什么好的主题做网站
  • 怎样建立自己的网站赚钱怎么运营
  • 网站建设广告宣传搭建自己的个人网站
  • 中国城投建设集团网站wordpress去除分类
  • 重庆做网站找谁深圳城建局
  • 10个企业网站设计欣赏怎么自己做微信推送新闻
  • 网站建设与维护A卷答案中国通信建设协会网站
  • wordpress连连支付百度seo新规则
  • 桃源网站建设北京有几家宽带网络公司
  • 网站建设 翰臣科技广告设计制作图片
  • 钓鱼网站 企业形象嘉兴网红桥在哪里
  • 网站内部链接如何进行优化建设说明书得制作需要哪些材料
  • 怎么在拼多多卖东西seo网站推广作用
  • 做网站前期需要准备什么小型网站制作
  • 可做影视网站的服务器公共场所建设网站
  • 高级网站开发培训wordpress 摄影 模板
  • 一站式服务包括哪些内容品牌网站建设 结构
  • 自适应网站导航是怎么做的百度指数数据分析平台官网