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

网站如何做原创智慧团建网站没有验证码

网站如何做原创,智慧团建网站没有验证码,dede后台删了 网站还有,商事登记服务工作室目录 一、引言 二、红黑树的概念与性质 2.1 红黑树的概念 2.2 红黑树的性质 三、红黑树的节点定义与结构 3.1 节点定义 四、红黑树的插入操作 4.1 插入步骤 4.2 插入代码实现 五、红黑树的验证 5.1 验证步骤 5.2 验证代码实现 六、红黑树迭代器的实现 6.1 迭代器的…

目录

 

一、引言

二、红黑树的概念与性质

2.1 红黑树的概念

2.2 红黑树的性质

三、红黑树的节点定义与结构

3.1 节点定义

四、红黑树的插入操作

4.1 插入步骤

4.2 插入代码实现

五、红黑树的验证

5.1 验证步骤

5.2 验证代码实现

六、红黑树迭代器的实现

6.1 迭代器的定义

6.2 迭代器的递增和递减操作

七、红黑树模拟实现  map  与  set 

7.1  set  的模拟实现

7.2  map  的模拟实现 

八、总结 


 

一、引言

在数据结构的世界里,平衡二叉搜索树是高效组织和查询数据的重要工具。红黑树作为平衡二叉搜索树的一种,因其良好的平衡特性和相对简单的实现,在许多场景中得到广泛应用,尤其是在C++ 的标准模板库(STL)中, map  和  set  等关联式容器的底层实现就依赖于红黑树。本文将深入探讨红黑树的原理、实现细节,并结合代码详细展示其在模拟  map  和  set  容器中的应用。

二、红黑树的概念与性质

2.1 红黑树的概念

红黑树是一种二叉搜索树,在每个节点上增加了一个存储位来表示节点的颜色,颜色可以是红色(Red)或黑色(Black)。通过对从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,从而达到近似平衡的状态。

2.2 红黑树的性质

1. 节点颜色性质:每个节点不是红色就是黑色。

 

2. 根节点性质:根节点是黑色的。

 

3. 红色节点性质:如果一个节点是红色的,则它的两个孩子节点是黑色的。

 

4. 黑色节点高度性质:对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

 

5. 叶子节点性质:每个叶子节点(此处的叶子节点指的是空节点)都是黑色的。

 

这些性质保证了红黑树的最长路径不会超过最短路径的两倍,使得树的高度相对平衡,从而在插入、删除和查找操作上都能保持高效。

三、红黑树的节点定义与结构

3.1 节点定义

在C++ 中,我们可以如下定义红黑树的节点:

cpp// 节点的颜色enum Color {RED, BLACK};// 红黑树节点的定义template<class ValueType>struct RBTreeNode{RBTreeNode(const ValueType& data = ValueType(), Color color = RED): _pLeft(nullptr), _pRight(nullptr), _pParent(nullptr), _data(data), _color(color){}RBTreeNode<ValueType>* _pLeft; // 节点的左孩子RBTreeNode<ValueType>* _pRight; // 节点的右孩子RBTreeNode<ValueType>* _pParent; // 节点的双亲(红黑树需要旋转,为了实现简单给出该字段)ValueType _data; // 节点的值域Color _color; // 节点的颜色};

 

这里将节点的默认颜色设为红色,主要是为了在插入新节点时,尽量减少对树结构调整的次数。因为插入红色节点比插入黑色节点更不容易破坏红黑树的性质,后续可以通过旋转和变色操作来恢复性质。3.2 红黑树结构

为了方便实现关联式容器,我们在红黑树的实现中增加一个头结点。头结点颜色为黑色,其  _pParent  域指向红黑树的根节点, _pLeft  域指向红黑树中最小的节点, _pRight  域指向红黑树中最大的节点。以下是红黑树类的基本框架:

cpptemplate<class K, class ValueType, class KeyOfValue>class RBTree{typedef RBTreeNode<ValueType> Node;typedef Node* PNode;public:typedef RBTreeIterator<ValueType, ValueType*, ValueType&> Iterator;RBTree();~RBTree();// 迭代器相关Iterator Begin() { return Iterator(_pHead->_pLeft); }Iterator End() { return Iterator(_pHead); }// 插入操作pair<Iterator, bool> Insert(const ValueType& data);// 清空树void Clear();// 查找操作Iterator Find(const K& key);// 容量相关size_t Size() const;bool Empty() const;private:PNode _pHead;size_t _size; // 红黑树中有效节点的个数};

 

四、红黑树的插入操作

4.1 插入步骤

红黑树的插入操作分为两步:

 

1. 按照二叉搜索树规则插入新节点:从根节点开始,根据新节点值与当前节点值的大小比较,向左或向右遍历树,直到找到合适的插入位置,插入新节点。新插入节点默认颜色为红色。

 

2. 检测并修复红黑树性质:由于新插入节点为红色,可能会违反红黑树的性质(主要是性质3:不能有连在一起的红色节点),此时需要对树进行调整,通过旋转和变色操作来恢复红黑树的性质。

4.2 插入代码实现

cpptemplate<class K, class ValueType, class KeyOfValue>pair<typename RBTree<K, ValueType, KeyOfValue>::Iterator, bool> RBTree<K, ValueType, KeyOfValue>::Insert(const ValueType& data){PNode& pRoot = _pHead->_pParent;if (nullptr == pRoot){pRoot = new Node(data, BLACK);pRoot->_pParent = _pHead;_pHead->_pLeft = _pHead->_pRight = pRoot;_size++;return make_pair(Iterator(pRoot), true);}KeyOfValue kofv;PNode pCur = pRoot;PNode pParent = nullptr;while (pCur){if (kofv(pCur->_data) > kofv(data)){pParent = pCur;pCur = pCur->_pLeft;}else if (kofv(pCur->_data) < kofv(data)){pParent = pCur;pCur = pCur->_pRight;}else{return make_pair(Iterator(pCur), false);}}pCur = new Node(data);pCur->_pParent = pParent;if (kofv(pParent->_data) > kofv(data)){pParent->_pLeft = pCur;if (_pHead->_pLeft == _pHead){_pHead->_pLeft = pCur;}}else{pParent->_pRight = pCur;if (_pHead->_pRight == _pHead){_pHead->_pRight = pCur;}}_size++;// 检测并修复红黑树性质while (pParent && pParent->_color == RED){PNode grandFather = pParent->_pParent;if (pParent == grandFather->_pLeft){PNode uncle = grandFather->_pRight;// 情况一:叔叔节点存在且为红if (uncle && uncle->_color == RED){pParent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;pCur = grandFather;pParent = pCur->_pParent;}else{// 情况二:叔叔节点不存在或为黑if (pCur == pParent->_pRight){_RotateLeft(pParent);swap(pParent, pCur);}pParent->_color = BLACK;grandFather->_color = RED;_RotateRight(grandFather);}}else{PNode uncle = grandFather->_pLeft;if (uncle && uncle->_color == RED){pParent->_color = BLACK;uncle->_color = BLACK;grandFather->_color = RED;pCur = grandFather;pParent = pCur->_pParent;}else{if (pCur == pParent->_pLeft){_RotateRight(pParent);swap(pParent, pCur);}pParent->_color = BLACK;grandFather->_color = RED;_RotateLeft(grandFather);}}}_pHead->_pParent->_color = BLACK;return make_pair(Iterator(pCur), true);}

上述代码中, _RotateLeft  和  _RotateRight  分别是左旋和右旋操作的函数,实现如下:

cpptemplate<class K, class ValueType, class KeyOfValue>void RBTree<K, ValueType, KeyOfValue>::_RotateLeft(PNode pParent){PNode pSubR = pParent->_pRight;PNode pSubRL = pSubR->_pLeft;pParent->_pRight = pSubRL;if (pSubRL){pSubRL->_pParent = pParent;}pSubR->_pLeft = pParent;PNode pPParent = pParent->_pParent;pParent->_pParent = pSubR;if (pPParent == nullptr){_pHead->_pParent = pSubR;}else if (pPParent->_pLeft == pParent){pPParent->_pLeft = pSubR;}else{pPParent->_pRight = pSubR;}pSubR->_pParent = pPParent;}template<class K, class ValueType, class KeyOfValue>void RBTree<K, ValueType, KeyOfValue>::_RotateRight(PNode pParent){PNode pSubL = pParent->_pLeft;PNode pSubLR = pSubL->_pRight;pParent->_pLeft = pSubLR;if (pSubLR){pSubLR->_pParent = pParent;}pSubL->_pRight = pParent;PNode pPParent = pParent->_pParent;pParent->_pParent = pSubL;if (pPParent == nullptr){_pHead->_pParent = pSubL;}else if (pPParent->_pLeft == pParent){pPParent->_pLeft = pSubL;}else{pPParent->_pRight = pSubL;}pSubL->_pParent = pPParent;}

五、红黑树的验证

 

5.1 验证步骤

红黑树的检测分为两步:

 

1. 检测是否满足二叉搜索树性质:通过中序遍历,检查遍历结果是否为有序序列。

 

2. 检测是否满足红黑树性质:检查根节点是否为黑色,以及每条路径上黑色节点的个数是否相同等性质。

5.2 验证代码实现

cpptemplate<class K, class ValueType, class KeyOfValue>bool RBTree<K, ValueType, KeyOfValue>::IsValidRBTree(){PNode pRoot = _pHead->_pParent;// 空树也是红黑树if (nullptr == pRoot){return true;}// 检测根节点是否为黑色if (pRoot->_color!= BLACK){std::cout << "违反红黑树性质二:根节点必须为黑色" << std::endl;return false;}// 获取任意一条路径中黑色节点的个数size_t blackCount = 0;PNode pCur = pRoot;while (pCur){if (pCur->_color == BLACK){blackCount++;}pCur = pCur->_pLeft;}// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数size_t k = 0;return _IsValidRBTree(pRoot, k, blackCount);}template<class K, class ValueType, class KeyOfValue>bool RBTree<K, ValueType, KeyOfValue>::_IsValidRBTree(PNode pRoot, size_t k, const size_t blackCount){// 走到null之后,判断k和black是否相等if (nullptr == pRoot){if (k!= blackCount){std::cout << "违反性质四:每条路径中黑色节点的个数必须相同" << std::endl;return false;}return true;}// 统计黑色节点的个数if (pRoot->_color == BLACK){k++;}// 检测当前节点与其双亲是否都为红色PNode pParent = pRoot->_pParent;if (pParent && pParent->_color == RED && pRoot->_color == RED){std::cout << "违反性质三:没有连在一起的红色节点" << std::endl;return false;}return _IsValidRBTree(pRoot->_pLeft, k, blackCount) &&_IsValidRBTree(pRoot->_pRight, k, blackCount);}

 

六、红黑树迭代器的实现

6.1 迭代器的定义

迭代器是红黑树与用户交互的重要接口,它可以方便地遍历红黑树。我们定义迭代器类如下:

cpptemplate<class ValueType, class Pointer, class Reference>class RBTreeIterator{typedef RBTreeNode<ValueType> Node;typedef RBTreeIterator<ValueType, Pointer, Reference> Self;public:RBTreeIterator(Node* node = nullptr) : _pNode(node) {}Reference operator*() { return _pNode->_data; }Pointer operator->() { return &(_pNode->_data); }Self& operator++(){_Increament();return *this;}Self operator++(int){Self tmp(*this);_Increament();return tmp;}Self& operator--(){_Decreament();return *this;}Self operator--(int){Self tmp(*this);_Decreament();return tmp;}bool operator==(const Self& s) const { return _pNode == s._pNode; }bool operator!=(const Self& s) const { return _pNode!= s._pNode; }private:void _Increament(){if (_pNode->_pRight){_pNode = _pNode->_pRight;while (_pNode->_pLeft){_pNode = _pNode->_pLeft;}}else{Node* pParent = _pNode->_pParent;while (pParent && _pNode == pParent->_pRight){_pNode = pParent;pParent = pParent->_pParent;}_pNode = pParent;}}void _Decreament(){if (_pNode->_color == RED && _pNode->_pParent->_pParent == _pNode){_pNode = _pNode->_pRight;}else if (_pNode->_pLeft){_pNode = _pNode->_pLeft;while (_pNode->_pRight){_pNode = _pNode->_pRight;}}else{Node* pParent = _pNode->_pParent;while (pParent && _pNode == pParent->_pLeft){_pNode = pParent;pParent = pParent->_pParent;}_pNode = pParent;}}Node* _pNode;};

 

6.2 迭代器的递增和递减操作

迭代器的递增操作  operator++  用于找到当前节点的下一个节点。如果当前节点有右子树,那么下一个节点就是右子树中最左侧的节点;如果当前节点没有右子树,则向上查找,直到找到一个是其双亲节点左孩子的节点,该双亲节点就是下一个节点。

 

迭代器的递减操作  operator--  则相反,用于找到当前节点的前一个节点。如果当前节点是头结点且颜色为红色,那么前一个节点是右子树中最大的节点;如果当前节点有左子树,那么前一个节点就是左子树中最右侧的节点;如果当前节点没有左子树,则向上查找,直到找到一个是其双亲节点右孩子的节点,该双亲节点就是前一个节点。

七、红黑树模拟实现  map  与  set 

7.1  set  的模拟实现

 set  是一种关联式容器,其底层结构为红黑树。`在  set  中,每个元素的值同时也是其键值,元素是唯一且有序的。下面是  set  类的模拟实现代码:
 

cpp   
namespace bit
{template<class K>class set{private:// 定义仿函数用于提取键值struct KeyOfValue{const K& operator()(const K& key) const{return key;}};// 底层使用红黑树存储数据typedef RBTree<K, K, KeyOfValue> RBTreeType;public:typedef typename RBTreeType::Iterator iterator;set() {}// 迭代器相关iterator begin() { return _tree.Begin(); }iterator end() { return _tree.End(); }// 容量相关size_t size() const { return _tree.Size(); }bool empty() const { return _tree.Empty(); }// 插入操作pair<iterator, bool> insert(const K& data){return _tree.Insert(data);}// 清空操作void clear() { _tree.Clear(); }// 查找操作iterator find(const K& key) { return _tree.Find(key); }private:RBTreeType _tree;};
}


 
在上述代码中,通过定义  KeyOfValue  仿函数,将元素值直接作为键值。然后利用前面实现的红黑树类  RBTree  来存储和管理元素,对外提供  set  容器常用的接口,如插入、查找、遍历等。
 

7.2  map  的模拟实现
 


 map  也是关联式容器,它存储的是键值对( pair ),其中键值是唯一且有序的,通过键值可以快速查找对应的值。以下是  map  类的模拟实现:
 

cpp   
namespace bit
{template<class K, class V>class map{private:// 定义键值对类型typedef pair<K, V> valueType;// 定义仿函数用于提取键值struct KeyOfValue{const K& operator()(const valueType& v) const{return v.first;}};// 底层使用红黑树存储数据typedef RBTree<K, valueType, KeyOfValue> RBTreeType;public:typedef typename RBTreeType::Iterator iterator;map() {}// 迭代器相关iterator begin() { return _tree.Begin(); }iterator end() { return _tree.End(); }// 容量相关size_t size() const { return _tree.Size(); }bool empty() const { return _tree.Empty(); }// 插入操作pair<iterator, bool> insert(const valueType& data){return _tree.Insert(data);}// 重载 [] 运算符,方便通过键值访问对应的值V& operator[](const K& key){pair<iterator, bool> ret = _tree.Insert(valueType(key, V()));return ret.first->second;}const V& operator[](const K& key) const{iterator it = _tree.Find(key);return it->second;}// 清空操作void clear() { _tree.Clear(); }// 查找操作iterator find(const K& key) { return _tree.Find(key); }private:RBTreeType _tree;};
}


 
 
在  map  的实现中,通过  KeyOfValue  仿函数从键值对中提取键值。同样基于红黑树实现数据存储和管理,并且重载了  []  运算符,使得可以像使用数组一样通过键值方便地访问和修改对应的值。
 


八、总结
 


红黑树通过巧妙地利用节点颜色和一些性质,在保证树近似平衡的同时,实现了高效的插入、删除和查找操作。在C++ 中, map  和  set  等关联式容器借助红黑树的特性,为我们提供了快速、有序的数据存储和访问方式。通过深入理解红黑树的原理和实现细节,我们不仅能更好地使用这些容器,还能在遇到类似数据组织和查询需求时,灵活运用红黑树来设计高效的数据结构。
 
希望本文能帮助大家对红黑树及其在C++ 关联式容器中的应用有更清晰、深入的认识。如果有任何疑问或建议,欢迎交流探讨。

 


文章转载自:

http://IMxbqXy1.qcrhb.cn
http://WDKZRk9u.qcrhb.cn
http://Qq8F3pSt.qcrhb.cn
http://WrdcZrAi.qcrhb.cn
http://blH4KCDq.qcrhb.cn
http://W2JehSai.qcrhb.cn
http://1zDDZfeT.qcrhb.cn
http://7ci6JK9J.qcrhb.cn
http://hW3YbBT1.qcrhb.cn
http://FJ2Bz7Nq.qcrhb.cn
http://jVamW6S6.qcrhb.cn
http://8xoBTKgk.qcrhb.cn
http://qYKOB8FJ.qcrhb.cn
http://TI2dFIHZ.qcrhb.cn
http://H3n5DVsA.qcrhb.cn
http://06OCjGii.qcrhb.cn
http://KLAfPah7.qcrhb.cn
http://pNSbfuGB.qcrhb.cn
http://tDMGXq9a.qcrhb.cn
http://o7fRnTla.qcrhb.cn
http://W914iAD9.qcrhb.cn
http://fIm9CNIa.qcrhb.cn
http://SuVUHp7o.qcrhb.cn
http://TxonnA0I.qcrhb.cn
http://N45XEVP0.qcrhb.cn
http://cVFsKBfR.qcrhb.cn
http://CoiVd5l7.qcrhb.cn
http://RaUnkvOL.qcrhb.cn
http://Tzdgzyjg.qcrhb.cn
http://NBYvzCpR.qcrhb.cn
http://www.dtcms.com/wzjs/726870.html

相关文章:

  • 可以做cps合作的棋牌网站盲盒小程序加盟
  • 网站图片速度企业门户网站设计报告
  • wikidot怎么建设网站wordpress好用的文件管理
  • 怎么用wordpress搭建企业网站四川成都设计公司
  • 岳阳市规划局建设工程公示网站重庆网站设计方案
  • 网站 团队布局网站建设
  • 电商建网站wordpress 音乐播放器 歌词
  • 网站首页权重华为净亏26亿
  • 安徽建设银行官方网站制作html网站模板
  • 渭南市住房和城乡建设局官方网站wordpress吗
  • 开封网站建设培训班招远网站建设价格
  • 免费网站建站排行榜国家建设工程注册管理中心网站
  • php门户网站源码抖音企业服务平台
  • 网站建设竞标书wordpress页面半透明
  • 婚介网站建设新闻资讯app开发
  • 珠海手机网站开发带会员系统的网站模板
  • 做社情网站犯法怎么办网站建设如何传视频
  • 网站在百度上做推广怎样做深圳腾网站建设
  • 昌吉网站建设咨询电话汕头网站制作网站
  • 制作短链接网站wordpress注册头像
  • 怎么做公众号网站吗私募基金网站开发流程
  • 网站建设的实验小结昆明体育城微网站建设
  • 专业seo网站优化公司全国企业信息公示系统查询
  • 唐山网站建设托管wordpress怎么增加菜单
  • 湛江cms建站系统烟台市芝罘区住房和建设局网站
  • 做系统用什么网站好班级建设网站
  • 没有网站能做淘宝客吗wordpress 判断自定义栏目
  • 用layui做的网站网络建设的网站
  • 兰州网站建设博客微信公众号申请注册官网
  • 服务器做网站好公司的网站建设费用算什么费用