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

建个微网站多少钱tv网站建设

建个微网站多少钱,tv网站建设,中国核工业二三建设有限公司招聘,亳州是网站建设红黑树前言一、红黑树的概念(一)红黑树的规则(二)红黑树最长路径与最短路径(三)红黑树的效率二、红黑树的实现(一) 红黑树的结构(二) 红黑树的插入1.情况一2.情况二3.情况三4.插入代码示例(三)红黑树的验证三、红黑树整体代码示例总结前言 红黑树是在二叉搜索树的基础上多出一些…

红黑树

  • 前言
  • 一、红黑树的概念
    • (一)红黑树的规则
    • (二)红黑树最长路径与最短路径
    • (三)红黑树的效率
  • 二、红黑树的实现
    • (一) 红黑树的结构
    • (二) 红黑树的插入
      • 1.情况一
      • 2.情况二
      • 3.情况三
      • 4.插入代码示例
    • (三)红黑树的验证
  • 三、红黑树整体代码示例
  • 总结


前言

`
红黑树是在二叉搜索树的基础上多出一些变化规则,以此让左右子树趋近平衡。

注意:
红黑树是趋近平衡,AVL树才是平衡;
AVL和红黑树不论底层实现还是功能都基本上一致。

一、红黑树的概念

红⿊树是⼀棵⼆叉搜索树,他的每个结点增加⼀个存储位来表⽰结点的颜⾊,可以是红⾊或者⿊⾊。 通过对任何⼀条从根到叶⼦的路径上各个结点的颜⾊进⾏约束,红⿊树确保没有⼀条路径会⽐其他路径⻓出2倍,因⽽是接近平衡的。

(一)红黑树的规则

1. 每个结点不是红⾊就是⿊⾊   
2. 根结点是⿊⾊的    
3. 如果⼀个结点是红⾊的,则它的两个孩⼦结点必须是⿊⾊的,也就是说任意⼀条路径不会有连续的红⾊结点。   
4. 对于任意⼀个结点,从该结点到其所有NULL结点的简单路径上,均包含相同数量的⿊⾊结点 

说明:《算法导论》等书籍上补充了⼀条每个叶⼦结点(NIL)都是⿊⾊的规则。他这⾥所指的叶⼦结点不是传统的意义上的叶⼦结点,⽽是我们说的空结点,有些书籍上也把NIL叫做外部结点。NIL是为了⽅便准确的标识出所有路径,《算法导论》在后续讲解实现的细节中也忽略了NIL结点,所以我们知道⼀下这个概念即可。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

(二)红黑树最长路径与最短路径

• 由规则4可知,从根到NULL结点的每条路径都有相同数量的⿊⾊结点,所以极端场景下,最短路径就就是全是⿊⾊结点的路径,假设最短路径⻓度为bh(black height)。
• 由规则2和规则3可知,任意⼀条路径不会有连续的红⾊结点,所以极端场景下,最⻓的路径就是⼀⿊⼀红间隔组成,那么最⻓路径的⻓度为2*bh
• 综合红⿊树的4点规则⽽⾔,理论上的全⿊最短路径和⼀⿊⼀红的最⻓路径并不是在每棵红⿊树都存在的。假设任意⼀条从根到NULL结点路径的⻓度为x,那么bh <= h <= 2 * bh

(三)红黑树的效率

假设N是红⿊树树中结点数量,h最短路径的⻓度,那么2^ h − 1 <= N < 2 ^(2∗h) − 1 , 由此推出 h ≈ logN ,也就是意味着红⿊树增删查改最坏也就是⾛最⻓路径 2 ∗ logN ,那么时间复杂度还是 O(logN).
红⿊树的表达相对AVL树要抽象⼀些,AVL树通过⾼度差直观的控制了平衡。红⿊树通过4条规则的颜⾊约束,间接的实现了近似平衡,他们效率都是同⼀档次,但是相对⽽⾔,插⼊相同数量的结点,红⿊树的旋转次数是更少的,因为他对平衡的控制没那么严格。
在这里插入图片描述

二、红黑树的实现

红黑树的主要接口有插入、删除、查找、遍历。
其中,红黑树的删除、查找、遍历代码实现几乎和二叉树搜索树一致,故不再重复说明,可以参考[二叉搜索树]。(https://blog.csdn.net/2501_90956005/article/details/150230291?spm=1001.2014.3001.5501)

而红黑树的实现中最复杂的就是红黑树的插入,重点理解!

(一) 红黑树的结构

/ 枚举值表⽰颜⾊
enum Colour
{RED,BLACK
};
// 这⾥我们默认按key/value结构实现
template<class K, class V>
struct RBTreeNode
{// 这⾥更新控制平衡也要加⼊parent指针pair<K, V> _kv;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;Colour _col=RED;RBTreeNode(const pair<K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr){}
};
template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public://红黑树的常用接口实现//......private:Node* _root = nullptr;
};

(二) 红黑树的插入

首先,红黑树的插入要分为以下进行讨论:
说明:下图中假设我们把新增结点标识为c (cur),c的⽗亲节点标识为p(parent),p的⽗亲节点标识为g(grandfather),p的兄弟节点标识为u(uncle)
情况一:u存在且为红
情况二:u不存在或者是⿊⾊的,且插入节点靠近树的边缘,如图一。
情况三:u不存在或者是⿊⾊的,且插入节点靠近树的内部,如图二。

图一:
在这里插入图片描述

图二:
在这里插入图片描述

1.情况一

u存在且为红

这是三种情况中最简单的情况。
处理:c为红,p为红,g为⿊,u存在且为红,则将p和u变⿊,g变红。在把g当做新的c,继续往上更新。
图示:
在这里插入图片描述

2.情况二

u不存在或者是⿊⾊的,且插入节点靠近树的边缘

这种情况我们仍然像情况一样进行处理,就会破坏红黑树的结构规则,所以这里需要像AVL树一样进行旋转处理。

旋转分为向左旋、向右旋转。
下面是我画的抽象图:
其中,g为旋转函数传入参数,圈起来的内容表示关系无变化,连线内容表示关系出现变化。
在这里插入图片描述

代码示例:
注:旋转结束后要更新节点颜色。

//向右旋转
void Rotate_R(Node*& grandparent)
{Node* parent = grandparent->_left;Node* temp = parent->_right;Node* pgrandpaent = grandparent->_parent;grandparent->_left = temp;if (temp)temp->_parent = grandparent;parent->_right = grandparent;grandparent->_parent = parent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandpaent->_left = grandparent){pgrandpaent->_left = parent;parent->_parent = pgrandpaent;}else{pgrandpaent->_right= parent;parent->_parent = pgrandpaent;}}
}
//向左旋转
void Rotate_L(Node*& grandparent)
{Node* parent = grandparent;Node* temp = parent->_left;Node* pgrandparent = grandparent->_parent;grandparent->_right = temp;if (temp)temp->_parent = grandparent;grandparent->_parent = parent;parent->_left = grandparent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandparent->_left = grandparent){pgrandparent->_left = parent;parent->_parent = pgrandparent;}else{pgrandparent->_right = parent;parent->_parent = pgrandparent;}}
}

3.情况三

u不存在或者是⿊⾊的,且插入节点靠近树的内部

这中情况需要复用两次单次旋转来进行处理,且两次旋转必须为先左旋后右旋或者先右旋后左旋

然后再对节点颜色进行更新。

注:通过观察旋转前后变化图可以知道,节点颜色的更新可以只看结果,而不去注意过程。

4.插入代码示例

void Rotate_R(Node*& grandparent)
{Node* parent = grandparent->_left;Node* temp = parent->_right;Node* pgrandpaent = grandparent->_parent;grandparent->_left = temp;if (temp)temp->_parent = grandparent;parent->_right = grandparent;grandparent->_parent = parent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandpaent->_left = grandparent){pgrandpaent->_left = parent;parent->_parent = pgrandpaent;}else{pgrandpaent->_right= parent;parent->_parent = pgrandpaent;}}
}void Rotate_L(Node*& grandparent)
{Node* parent = grandparent;Node* temp = parent->_left;Node* pgrandparent = grandparent->_parent;grandparent->_right = temp;if (temp)temp->_parent = grandparent;grandparent->_parent = parent;parent->_left = grandparent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandparent->_left = grandparent){pgrandparent->_left = parent;parent->_parent = pgrandparent;}else{pgrandparent->_right = parent;parent->_parent = pgrandparent;}}}bool Insert(const pair<K, V>& kv)
{if (_root == nullptr){_root = new Node(kv.first,kv.second);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key > kv.first){parent = cur;cur = cur->_left;}else if (cur->_key < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv.first, kv.second);if (parent->_key>kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;while(parent&&parent->_col==RED){	Node* grandparent = parent->_parent;if (grandparent->_left == parent){Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else{if (parent->_left == cur){Rotate_R(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{Rotate_L(grandparent);Rotate_R(grandparent);grandparent->_col = RED;cur->_col = BLACK;}return true;}}else{Node* uncle = grandparent->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else{if (parent->_left == cur){Rotate_L(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{Rotate_R(grandparent);Rotate_L(grandparent);grandparent->_col = RED;cur->_col = BLACK;}break;}}}return true;
}

(三)红黑树的验证

在进行完红黑树的增删查操作后,我们可能会对红黑树的结果重新验证,判断它还是不是红黑树。
这里仅提供思路:
使用前序遍历,期间如果遍历到红色节点,对该节点的父节点颜色进行判断,如果父节点也为红色,那么他就不是红黑树,返回false;反之继续遍历,直到遍历结束返回true。

三、红黑树整体代码示例

#pragma once#include<iostream>
#include<string>using namespace std;enum Colour
{RED,BLACK
};template<typename K,typename V>
struct RBNode
{RBNode(const K& key,const V& value):_key(key),_value(value){}K _key;V _value;RBNode<K, V>* _parent=nullptr;RBNode<K, V>* _left=nullptr;RBNode<K, V>* _right=nullptr;Colour _col=RED;
};template<typename K,typename V>
class RBTree
{typedef RBNode<K, V> Node;
public:void Rotate_R(Node*& grandparent){Node* parent = grandparent->_left;Node* temp = parent->_right;Node* pgrandpaent = grandparent->_parent;grandparent->_left = temp;if (temp)temp->_parent = grandparent;parent->_right = grandparent;grandparent->_parent = parent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandpaent->_left = grandparent){pgrandpaent->_left = parent;parent->_parent = pgrandpaent;}else{pgrandpaent->_right= parent;parent->_parent = pgrandpaent;}}}void Rotate_L(Node*& grandparent){Node* parent = grandparent;Node* temp = parent->_left;Node* pgrandparent = grandparent->_parent;grandparent->_right = temp;if (temp)temp->_parent = grandparent;grandparent->_parent = parent;parent->_left = grandparent;if (grandparent == _root){_root = parent;parent->_parent = nullptr;}else{if (pgrandparent->_left = grandparent){pgrandparent->_left = parent;parent->_parent = pgrandparent;}else{pgrandparent->_right = parent;parent->_parent = pgrandparent;}}}bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv.first,kv.second);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;while (cur){if (cur->_key > kv.first){parent = cur;cur = cur->_left;}else if (cur->_key < kv.first){parent = cur;cur = cur->_right;}else{return false;}}cur = new Node(kv.first, kv.second);if (parent->_key>kv.first){parent->_left = cur;}else{parent->_right = cur;}cur->_parent = parent;while(parent&&parent->_col==RED){	Node* grandparent = parent->_parent;if (grandparent->_left == parent){Node* uncle = grandparent->_right;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else{if (parent->_left == cur){Rotate_R(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{Rotate_L(grandparent);Rotate_R(grandparent);grandparent->_col = RED;cur->_col = BLACK;}return true;}}else{Node* uncle = grandparent->_left;if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandparent->_col = RED;cur = grandparent;parent = cur->_parent;}else{if (parent->_left == cur){Rotate_L(grandparent);grandparent->_col = RED;parent->_col = BLACK;}else{Rotate_R(grandparent);Rotate_L(grandparent);grandparent->_col = RED;cur->_col = BLACK;}break;}}}return true;}void InOrder(){_InOrder(_root);}Node* Find(const K& key){if (_root == nullptr)return nullptr;Node* cur = _root;while (cur){if (key>cur->_key){cur = cur->_right;}else if (key < cur->_key){cur = cur->_left;}else{return cur;}}return nullptr;}private:void _InOrder(Node* root){if (root == nullptr)return;_InOrder(root->_left);cout << root->_key << " " << root->_value << endl;_InOrder(root->_right);}Node* _root=nullptr;
};

总结

红黑树的插入实现是红黑树学习的核心内容,对于插入的代码最好能自行实现一下,且实现过程中最好多画画图。
同时,红黑树也是map/set封装的底层实现,理解红黑树对于学习map/set打下基础。

http://www.dtcms.com/a/457282.html

相关文章:

  • Docker 说明与安装
  • Docker 镜像结构与相关核心知识总结
  • 容器技术与 Docker 入门部署
  • linux学习笔记(20)线程
  • Vue3后台表单快速开发
  • 前端技术栈 —— 创建React项目
  • 推荐一个 GitHub 开源项目信息卡片生成工具,支持Docker快速部署和API调用
  • 元宇宙的工业制造应用:重构生产、研发与供应链
  • 做美足网站违法吗北京网站建设哪家比较好
  • 2025版本的idea解决Git冲突
  • 深入浅出 HarmonyOS ArkTS:现代跨平台应用开发的语法基石
  • Spring boot 3.0整合RocketMQ不兼容的问题
  • 淮安制作企业网站莱芜金点子最新招聘
  • AI+机器人浪潮已至:是方舟还是巨浪?
  • Linux:虚拟世界的大门
  • 市桥网站建设培训数据库与网站建设
  • LangGraph学习笔记 (二)-10分钟搭建自己第一个Agent
  • Sutton:LLM 通往 AGI 的隐秘瓶颈
  • 吴恩达机器学习课程(PyTorch 适配)学习笔记大纲
  • 聊透自动驾驶系统:从“怎么跑”到“怎么聪明跑”
  • 网站建设属于什么职能wordpress建站教程
  • LeetCode 刷题【107. 二叉树的层序遍历 II、108. 将有序数组转换为二叉搜索树】
  • 宝塔服务器面板部署安装git通过第三方应用安装收费怎么办—bash: git: command not found解决方案-优雅草卓伊凡
  • 9. linux shell命令(6)Linux网络配置管理
  • 专做品质游的网站河东苏州网站建设
  • Spring的三级缓存原理 笔记251008
  • Coze源码分析-资源库-编辑数据库-后端源码-应用/领域/数据访问/基础设施层
  • 北京建设网站的公司兴田德润简介济南网站建设平台官网
  • 力扣 —— 动态规划(背包问题)
  • 基础微网站开发代理商wordpress图文模板