红黑树的迭代器

//红黑树的迭代器
template<class T>
struct RBTreeIterator
{typedef RBTreeNode<T>Node;typedef RBTreeIterator<T> Self;
public:RBTreeIterator(Node* pNode = nullptr):_pNode(pNode){}//具有指针操作T& operator*(){return _pNode->_data;//找值}T* operator->(){return &(operator*());}//可以移动Self& operator++(){Increament();return *this;}Self operator++(int){Self temp(*this);Increament(); //往后走一步return temp;}Self& operator--(){DeIncreament();return *this;}Self operator--(int){Self temp(*this);DeIncreament();return temp;}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{//比_pNode大的元素可能在它的双亲中Node* pParent = _pNode->_pParent;while (_pNode == pParent->_pRight){_pNode = pParent;pParent = _pNode->_pParent;}//根结点没有右子树&&迭代器在根结点的位置if (_pNode->_pRight!=pParent)_pNode = pParent; //把pNode放到双亲的位置}}void DeIncreament(){if (_pNode->_pParent->_pParent == _pNode&& RED == _pNode->_color){_pNode = _pNode->_pRight;}else if (_pNode->_pLeft){//如果左子树存在,应该在左子树中找最大的结点_pNode = _pNode->_pLeft;while (_pNode->_pRight)_pNode = _pNode->_pRight;}else{//向上找Node* pParent = _pNode->_pParent;while (_pNode == pParent->_pLeft){_pNode = pParent;pParent = _pNode->_pParent;}//begin不可能再减_pNode = pParent;}}
private:Node* _pNode;
};

红黑树的改造

template<class T,class KOFV>
class RBTree
{typedef RBTreeNode<T> Node;
public:typedef RBTreeIterator<T> iterator;public:RBTree():_size(0){_pHead = new Node;_pHead->_pLeft = _pHead;_pHead->_pRight = _pHead;//构造里已经将双亲给成空}iterator begin(){return iterator(_pHead->_pLeft);}iterator end(){return iterator(_pHead);}pair<iterator,bool> Insert(const T&data){Node*& pRoot = GetRoot(); //必须以引用的方式进行接受Node* pNewNode = nullptr;if (nullptr == pRoot) //树为空,创建根结点{pNewNode = pRoot = new Node(data, BLACK);pRoot->_pParent = _pHead;//只有一个结点,head就是根节点的双亲}else{//说明树已经不为空了//1.按照二叉搜索树的性质找到带插入结点在红黑树的位置Node* pCur = pRoot;Node* pParent = nullptr;while (pCur){pParent = pCur;//标记双亲位置if (KOFV()(data) < KOFV()(pCur->_data))pCur = pCur->_pLeft;else if (KOFV()(data) > KOFV()(pCur->_data))pCur = pCur->_pRight;else//相同不插入return make_pair(iterator(pCur),false);}//2. 插入新结点pNewNode = pCur = new Node(data);if (KOFV()(data) < KOFV()(pParent->_data))pParent->_pLeft = pCur;elsepParent->_pRight = pCur;//3. 更新双亲位置pCur->_pParent = pParent;//以上没错//4.检测:是否新结点插入后连在一起的红色结点while (pParent != _pHead && RED == pParent->_color){Node* granderFather = pParent->_pParent;if (pParent == granderFather->_pLeft){//叔叔结点在右侧Node* uncle = granderFather->_pRight;//情况一:叔叔结点存在,且为红if (uncle && RED == uncle->_color){pParent->_color = BLACK;uncle->_color = BLACK;granderFather->_color = RED;pCur = granderFather;pParent = pCur->_pParent;}//以上没问题else{//情况三if (pCur == pParent->_pRight) //情况三{//转变成情况二RotateLeft(pParent);swap(pParent, pCur);}//情况二pParent->_color = BLACK;granderFather->_color = RED;RotateRight(granderFather);}//以上没问题}else{//叔叔结点在左侧Node* uncle = granderFather->_pLeft;//情况一的反情况if (uncle && uncle->_color == RED){pParent->_color = BLACK;uncle->_color = BLACK;granderFather->_color = RED;pCur = granderFather;pParent = pCur->_pParent;}//以上没问题else{//情况三的反情况if (pCur == pParent->_pLeft)   /**/{//情况三的反情况变成情况二的反情况RotateRight(pParent);swap(pParent, pCur);}//情况二反情况处理pParent->_color = BLACK;granderFather->_color = RED;RotateLeft(granderFather);}//以上没问题}}}//5.调整头结点的左右指针域//保证根节点是黑色++_size;pRoot->_color = BLACK;_pHead->_pLeft = LeftMost();_pHead->_pRight = RightMost();return make_pair(iterator(pNewNode), true);}iterator Find(const T& data)const{Node* pCur = _pHead->_pParent;while (pCur){if (KOFV()(data) == KOFV()(pCur->_data))return iterator(pCur);else if (KOFV()(data) < KOFV()(pCur->_data))pCur = pCur->_pLeft;elsepCur = pCur->_pRight;}return end();}void InOrder(){_InOrder(GetRoot());}//检测红黑树bool IsValidRBTree(){Node* pRoot = GetRoot();if (nullptr == pRoot)return true;if (pRoot->_color != BLACK){cout << "违反性质2:根结点颜色必须为黑色" << endl;return false;}//获取一条路径中结点的个数size_t blackCount = 0; //基准值Node* pCur = pRoot;while (pCur){if (pCur->_color == BLACK)blackCount++;pCur = pCur->_pLeft;}size_t pathBlack = 0; //每条路径中的黑色结点个数return _IsValidRBTree(pRoot, blackCount, pathBlack);}bool Empty()const{return nullptr = _pHead->_pParent;}size_t Size()const{return _size;}
protected:bool _IsValidRBTree(Node* pRoot, size_t blackCount, size_t pathBlack){if (nullptr == pRoot)return true;if (pRoot->_color == BLACK)pathBlack++;//检测性质3Node* pParent = pRoot->_pParent;if (pParent != _pHead && pParent->_color == RED&&pRoot->_color == RED){cout << "违反性质3:不能有连在一起的红色结点" << endl;return false;}if (nullptr == pRoot->_pLeft&&nullptr == pRoot->_pRight){//一条路径到叶子if (blackCount != pathBlack){cout << "违反了性质4:每条路径中黑色结点个数必须相同" << endl;return false;}}return _IsValidRBTree(pRoot->_pLeft, blackCount, pathBlack) &&_IsValidRBTree(pRoot->_pRight, blackCount, pathBlack);}Node* LeftMost(){//得到根节点Node* pRoot = GetRoot();if (nullptr == pRoot)return _pHead;Node* pCur = pRoot;//找到最左侧结点while (pCur->_pLeft)pCur = pCur->_pLeft;return pCur;}Node* RightMost(){//得到根节点Node* pRoot = GetRoot();if (nullptr == pRoot)return _pHead;Node* pCur = pRoot;//找到最右侧结点while (pCur->_pRight)pCur = pCur->_pRight;return pCur;}void RotateLeft(Node* pParent){Node* pSubR = pParent->_pRight;Node* pSubRL = pSubR->_pLeft;pParent->_pRight = pSubRL;if (pSubRL)pSubRL->_pParent = pParent;pSubR->_pLeft = pParent;Node* pPParent = pParent->_pParent;pParent->_pParent = pSubR;pSubR->_pParent = pPParent;if (pPParent == _pHead)GetRoot() = pSubR;else{if (pPParent->_pLeft == pParent)pPParent->_pLeft = pSubR;elsepPParent->_pRight = pSubR;}}void RotateRight(Node* pParent){Node* pSubL = pParent->_pLeft;Node* pSubLR = pSubL->_pRight;pParent->_pLeft = pSubLR;if (pSubLR)pSubLR->_pParent = pParent;pSubL->_pRight = pParent;Node* pPParent = pParent->_pParent;pParent->_pParent = pSubL;pSubL->_pParent = pPParent;//pParent是根结点if (pPParent == _pHead)GetRoot() = pSubL;else{//非根结点if (pPParent->_pLeft == pParent)pPParent->_pLeft = pSubL;elsepPParent->_pRight = pSubL;}}Node*& GetRoot()  //head是new出来的,head存在parent一定存在,按引用方式返回没有问题{//得到根节点,也就是头结点的下一个结点return _pHead->_pParent;}void _InOrder(Node* pRoot){if (pRoot){_InOrder(pRoot->_pLeft);cout << pRoot->_data << " ";_InOrder(pRoot->_pRight);}}
private:Node* _pHead;size_t _size; //记录红黑树中有效结点的个数
};
struct KeyValue
{int operator()(int data){return data;}
};

模拟实现map和set

map<key,value>----比较方式:键值对中的key
set:key ----比较方式:直接用其元素比较

map模拟实现

#pragma once
#include"RBTree.h"namespace bite
{//只需要封装一个红黑树template<class K, class V>class map{typedef pair<K, V> ValueType;struct KeyOfValue{const K& operator()(const ValueType & data){return data.first;}};public://编译器有可能将iterator当成静态成员变量来处理typename typedef RBTree<ValueType, KeyOfValue>::iterator iterator;//明确的告诉编译器iterator 时红黑树中的一种类型public:map():_t(){}iterator begin(){return _t.begin();}iterator end(){return _t.end();}pair<iterator, bool> insert(const ValueType&data){return _t.Insert(data);}size_t size()const{return _t.Size();}bool Empty()const{return _t.Empty();}iterator find(const K& key){return  _t.Find(make_pair(key,V()));}V& operator[](const K& key){return (*(_t.Insert(ValueType(key, V()))).first).second;}private:RBTree<ValueType,KeyOfValue> _t;};
}#include<string>
#include<iostream>
using namespace std;
void TestMap()
{bite::map<std::string, std::string>m;m.insert(pair<std::string,std::string>("2222","11111"));m.insert(make_pair("1111","1111"));m["0000"] = "0000";cout << m.size() << endl;for (auto e : m)cout << e.first << " " << e.second << endl;cout << endl;
}

set模拟实现

namespace bite
{//只需要封装一个红黑树template<class K>class set{typedef K ValueType;struct KeyOfValue{const K& operator()(const ValueType & data){return data;}};public://编译器有可能将iterator当成静态成员变量来处理typename typedef RBTree<ValueType, KeyOfValue>::iterator iterator;//明确的告诉编译器iterator 时红黑树中的一种类型public:set():_t(){}iterator begin(){return _t.begin();}iterator end(){return _t.end();}pair<iterator, bool> insert(const ValueType&data){return _t.Insert(data);}size_t size()const{return _t.Size();}bool Empty()const{return _t.Empty();}iterator find(const K& key){return  _t.Find(key);}private:RBTree<ValueType, KeyOfValue> _t;};
}
#include<string>
#include<iostream>
using namespace std;
void TestSet()
{bite::set<std::string>m;m.insert("2222");m.insert("11111");m.insert("11111");cout << m.size() << endl;for (auto e : m)cout << e << endl;cout << endl;
}

模拟实现STL中map和set容器相关推荐

  1. C++ STL : 模拟实现STL中的关联式容器unordered_map/unordered_set

    目录 unordered_map/unordered_set unordered_map/unordered_set与map/set的区别 底层哈希桶的改造 仿函数 Key值的获取方法 hash(ke ...

  2. C++ STL : 模拟实现STL中的关联式容器map和set

    目录 关联式容器 键值对 底层红黑树的改造 仿函数 红黑树的迭代器 完整代码 set set的文档介绍 set的实现 map map的文档介绍 map的实现 operator[] 完整代码 multi ...

  3. C++ STL : 模拟实现STL中的容器适配器stack和queue

    目录 什么是容器适配器 stack stack的文档介绍-(来自cplusplus) stack的实现 queue queue的文档介绍-(来自cplusplus) queue的实现 什么是容器适配器 ...

  4. c++ map是有序还是无序的_C++ STL中Map的按Key排序和按Value排序

    map是用来存放键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行存储就是个不错的选择. 我们这样定义 ...

  5. stl中map函数_map :: empty()函数以及C ++ STL中的Example

    stl中map函数 C ++ STL映射:: empty() (C++ STL map::empty()) It is built-in function in C++ STL and used to ...

  6. STL 中map的用法详解

    STL 中map的用法详解 Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可 ...

  7. stl中map函数_map :: max_size()函数,以及C ++ STL中的Example

    stl中map函数 C ++ STL映射:: max_size() (C++ STL map::max_size() ) It returns the maximum number of elemen ...

  8. C++ STL中Map的按Key排序和按Value排序

    map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区分),我们用map来进行 ...

  9. 【贪玩巴斯】C++提高编程,掌握STL中最关键的容器技术~(三){map、set、list、queue、stack 五大容器一篇解决!} //2021-08-25

    //  day_03 //  Created by AchesonD16 贪玩巴斯 on 2021/8/19. 1. stack容器 (栈) 1.1 stack 基本概念 栈 概念: stack是一种 ...

最新文章

  1. gdb info frame信息解释
  2. LOJ 2339 「WC2018」通道——边分治+虚树
  3. docker安装mysql以及设置navicat远程访问
  4. Matlab中vpa一直在忙,matlab数据类型转换遇到问题,及解决办法,sym,double ,vpa转换...
  5. 离线安装SilverLight
  6. java osm_OSM初识(三)OSM Data
  7. bind9 dlz mysql_利用BIND+DLZ+MYSQL构建企业智能DNS
  8. 为什么 SD-WAN 很重要?
  9. win10将HTML动态做桌面壁纸,用win10自带工具,win10专业版简易制作动态壁纸教程...
  10. 超级右键 iRightMouse --Mac强大的右键菜单设置工具
  11. SAP中通过定制开发在寄售结算MRKO中实现发票校验功能
  12. php 安装参数 ./configure
  13. linux-版本相关
  14. 8. 使用 Azure Function
  15. 国津谈|巨头们会来分企业级管理软件一杯羹吗?
  16. URL中的%2C是什么?
  17. 蓝牙防丢器实现安卓的BLE接口编程
  18. 一个自用Typora魔改主题
  19. 学校类站群网站建设管理
  20. python如何编游戏_手把手教你用python写游戏

热门文章

  1. 解决win7下无法安装突击者NO.69驱动,“WINDOWS已找到设备的驱动程序,但在试图安装它时错误”...
  2. 教务管理及教材订购系统设计文档
  3. Spark2.3(三十五)Spark Structured Streaming源代码剖析(从CSDN和Github中看到别人分析的源代码的文章值得收藏)...
  4. “景驰科技杯”2018年华南理工大学程序设计竞赛 A. 欧洲爆破(思维+期望+状压DP)...
  5. label 标签里面元素点击事件
  6. onesignal php,PHP FPM源代码反刍品味之五:信号signal处理
  7. 启航考研计算机课程,计算机考研专业课如何备考
  8. android fragment界面滑动切换效果,Android App中使用ViewPager+Fragment实现滑动切换效果...
  9. Java小青蛙跳台街,算法-青蛙跳台阶详解
  10. 【C++进阶】C++创建文件/屏幕输出流类(将信息同时输出到文件和屏幕)