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

医院网站开发公司网站关键词搜索排名优化

医院网站开发公司,网站关键词搜索排名优化,暖通毕业设计代做网站,deals网站建设目录 一、红黑树概念 二、红黑树节点结构设计 三、插入操作 处理情况1 处理情况2 处理情况3 插入总结: 四、插入操作源码 五、红黑树验证 一、红黑树概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色&#xff0…

目录

一、红黑树概念

 二、红黑树节点结构设计

三、插入操作

 处理情况1

 处理情况2

处理情况3

 插入总结:

 四、插入操作源码

五、红黑树验证


一、红黑树概念

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

 红黑树还必须满足以下规则:

1. 每个结点不是红色就是黑色(非红即黑)
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的(没有连续的红色)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点(每条路径上黑色节点的数量相等)(从这一规则也可以得出,在插入一新节点时,该节点必须为红,才会满足该条件)
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点

 规则四演示:

 二、红黑树节点结构设计

 因为红黑树节点非红即黑,所以可以用枚举的思想来例举红节点和黑节点。因为在插入的过程中,可能会存在翻转的情况,所以就需要一个节点的父节点_parent,左孩子_left,右孩子_right。

enum Colour
{RED,BLACK
};template<class K, class V>
struct RBTreeNode
{ RBTreeNode<K, V>* _left;  // 左孩子RBTreeNode<K, V>* _right;  // 右孩子RBTreeNode<K, V>* _parent;  // 红黑树需要旋转,为了实现简单给出该字段pair<K, V> _kv;  //值域Colour _col;  //颜色RBTreeNode(const pair<K, V>& kv)  //初始化:_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv){}
};

三、插入操作

根据规则4,可以得出在插入一个新节点的时候,这个节点一定是为红色的(上已证)。在插入红色节点的时候可能还是会造成红红节点的冲突(违反规则3),所以我们还需要进行变色+旋转的处理方法

 在插入新节点后,因为新节点的默认颜色是红色,因此:如果其父亲节点的颜色是黑色,没有违反红黑树任何规则,则不需要调整;但当新插入节点的父亲节点颜色为红色时,就违反了规则3不能有连在一起的红色节点,此时需要对红黑树分情况来讨论:为方便我们进行变色和旋转的处理,我们定义父亲节点为p,叔叔节点为u,祖父节点为g,当前节点为cur(新增)。实际上,根据红黑树的规则,我们可以确定要发生变色或旋转操作时,cur、p、g节点一定是红、红、黑,如果不满足这种情况,那么肯定这颗红黑树在次之前就违背的红黑树的规则。所以变化操作主要取决于叔叔节点u的颜色。如下抽象图表示,s/b/c/de代表的是满足规则的子树。

 

 处理情况1

cur为红,p为红,g为黑,u存在且为红

 处理方法:叔叔u和父亲p变黑,祖父g变红,再往上进行处理,如果g是根节点,需要把g再变黑,因为根节点必须是黑(规则2)。再往上处理的过程中因为会存在当前g的父节点为红的情况,又再次冲突,所以要进行处理.

 

 

 处理情况2

cur为红且在外侧,p为红,g为黑,u不存在/u存在且为黑

u的两种情况:

1.如果u节点不存在,则cur一定是新插入节点,因为如果cur不是新插入节点,则cur和p一定有一个节点的颜色是黑色,就不满足性质4:每条路径黑色节点个数相同。

 

⒉.如果u节点存在,则其一定是黑色的,那么cur节点原来的颜色一定是黑色的,现在看到其是红色的原因是因为cur的子树在调整的过程中将cur节点的颜色由黑色改成红色。
 

 

 处理方法:单旋+变色。按p节点进行右旋,此时p为红,g为黑,再将p和g的颜色进行交换,即满足红黑树规则。(若p为g的右孩子,cur为p的右孩子,则进行左单旋转,p、g变色--p变黑,g变红)。处理完成后不需要再进行往上处理,因为此时p为黑,p的父亲节点为黑或红都不会对树产生影响。

处理情况3

cur为红且在内侧,p为红,g为黑,u不存在/u存在且为黑

 处理方法:双旋+变色

u不存在情况:

若p在g的左侧,cur在内侧,则先对g的左子树进行左旋,在对g这棵子树进行右旋;反之,p在g的右侧,cur在内存,就先右旋再左旋再交换cur和g的颜色。

 u存在情况:

像这种情况,都是由情况一经过处理后得来的,此时就需要先对g的左子树进行左单旋,旋转后,就会变为情况二,此时再根据情况二的解决方法进行解决,右旋+变色,旋转后将cur和g的颜色进行交换即可。(如果最开始p是在右子树,则操作相反,先右旋再左旋变色。)

 插入总结:

1.红黑树插入的节点一定为红色

2.处理三种可能的情况关键在于叔叔节点u

3.u存在且为红(情况一),将p和u节点变黑,g节点变红,若g为根节点就将g变为黑色

4.情况二和情况三都是由情况一经过变化后得来的

4.u不存在或存在且为黑,插入的节点cur在p的外侧(情况二),若p是左子树就进行右旋+交换p、g颜色;若p是右子树,反之,左旋+交换颜色。

5.u不存在或存在且为黑,插入节点cur在p的内侧(情况三),若p是左子树就先进行左旋变为情况二,再进行右旋+交换颜色。反之p为右子树,先进行右旋变为情况二,在进行左旋+交换颜色。

 四、插入操作源码

插入源码: 

	bool Insert(const pair<K, V>& kv){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);cur->_col = RED;if (parent->_kv.first < kv.first){parent->_right = cur;}else{parent->_left = cur;}cur->_parent = parent;while (parent && parent->_col == RED)  // parent为红色就需要变色处理,因为插入的节点为红{Node* grandfater = parent->_parent;  //祖父节点assert(grandfater);assert(grandfater->_col == BLACK);// 关键看叔叔if (parent == grandfater->_left){Node* uncle = grandfater->_right;  //叔叔节点// 情况一 : uncle存在且为红,变色+继续往上处理if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfater->_col = RED;// 继续往上处理cur = grandfater;  // 往上处理的时候把祖父当做插入的节点即curparent = cur->_parent;}// 情况二+三:uncle不存在 + 存在且为黑else{// 情况二:右单旋+变色//     g //   p   u// cif (cur == parent->_left){RotateR(grandfater);parent->_col = BLACK;grandfater->_col = RED;}else{// 情况三:左右单旋+变色//      g //   p     u//     cRotateL(parent);RotateR(grandfater);cur->_col = BLACK;grandfater->_col = RED;}break;}}else // (parent == grandfater->_right){Node* uncle = grandfater->_left;// 情况一if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfater->_col = RED;// 继续往上处理cur = grandfater;parent = cur->_parent;}else{// 情况二:左单旋+变色//     g //   u   p//         cif (cur == parent->_right){RotateL(grandfater);parent->_col = BLACK;grandfater->_col = RED;}else{// 情况三:右左单旋+变色//     g //   u   p//     cRotateR(parent);RotateL(grandfater);cur->_col = BLACK;grandfater->_col = RED;}break;}}}_root->_col = BLACK;return true;}

旋转操作的源码解析可以参考这篇博文:http://t.csdn.cn/iyMac

左旋:

	void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* ppNode = parent->_parent;subR->_left = parent;parent->_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 RotateR(Node* parent){Node* subL = parent->_left;Node* subLR = subL->_right;parent->_left = subLR;if (subLR){subLR->_parent = parent;}Node* ppNode = 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;}}

五、红黑树验证

验证方法:判断从根节点起的每一条子路径中的黑节点数是否相等(规则4)。利用递归的思想遍历每一条路径。再遍历第一条路径的时候,设置一个benchmark记录黑色节点数量,因为规则4,所以后面每一条路径的黑节点数应该都要与之相等,如果不等则不是红黑树。再遍历每一条路径的同时,也可以寻找是否存在连续的红节点(规则三),存在则不满足为红黑树。依次递归每一条路径。

源码:

	bool IsBalance(){if (_root == nullptr){return true;}if (_root->_col == RED){cout << "根节点不是黑色" << endl;return false;}// 黑色节点数量基准值int benchmark = 0;return PrevCheck(_root, 0, benchmark);}bool PrevCheck(Node* root, int blackNum, int& benchmark){if (root == nullptr){if (benchmark == 0)  // 遍历第一条路径的时候,记录他的黑节点数,后面每一条路径的黑节点数一个都和他相等{benchmark = blackNum;return true;}if (blackNum != benchmark){cout << "某条黑色节点的数量不相等" << endl;return false;}else{return true;}}if (root->_col == BLACK){++blackNum;}if (root->_col == RED && root->_parent->_col == RED){cout << "存在连续的红色节点" << endl;return false;}return PrevCheck(root->_left, blackNum, benchmark)&& PrevCheck(root->_right, blackNum, benchmark);}void TestRBTree()
{size_t N = 1000;srand(time(0));RBTree<int, int> t1;for (size_t i = 0; i < N; ++i){int x = rand();cout << "Insert:" << x << ":" << i << endl;t1.Insert(make_pair(x, i));}cout << "IsBalance:" << t1.IsBalance() << endl;  //打印1则是红黑树,否则不是
}

http://www.dt0577.cn/news/16612.html

相关文章:

  • 企业网站开发实训目的和意义沈阳cms建站模板
  • 青岛网站建设最便宜爱网站关键词查询工具长尾
  • wordpress友链顺序百度网站排名优化软件
  • 怎么用ftp管理网站网站制作步骤流程图
  • 成都装修公司哪家口碑最好官网seo哪家公司好
  • 同仁行业网站建设报价网站编辑怎么做
  • 株洲新闻网红网株洲站长春seo主管
  • 武汉通官网网站建设营销网站seo推广
  • 个人网站怎么做支付功能镇江交叉口优化
  • 企业网站的基本内容以及营销功能站长工具国产
  • 全响应式网站用什么做的网站优化的方式有哪些
  • 罗湖附近公司做网站建设哪家技术好青岛seo培训
  • wordpress安装百度站长资源平台福州seo结算
  • 检察院门户网站建设工作成效百度应用下载
  • 网站域名什么意思百度快照投诉
  • 直播网站开发长春网站优化流程
  • php就是做网站吗网站注册搜索引擎的目的是
  • 网站应用程序池北京百度seo公司
  • wordpress企业文化模板下载网络seo哈尔滨
  • 电子商务网站建设与维护管理网站seo优化推广外包
  • 软件班级网站建设主题免费观看行情软件网站下载
  • 威海网站优化新余seo
  • 平台网站制作广告公司名称
  • 焦作网站建设哪家专业营销型网站建设报价
  • 哪个网站做视频有钱挣网络优化的流程
  • wordpress模板网站互联网推广招聘
  • 云南品牌网站开发网页推广链接怎么做
  • 网站中的滚动字幕怎么做搜索引擎推广方式
  • 银川网站怎么做seo网络项目推广平台
  • 网站推广费用ihanshi互动营销名词解释