this[]的用法,自我指定向key-value

C 总会看到某个类,暂时命名为 Class1直接可以存储对应的key-value键值对

例如 class1["key1"]=value1,class["key2"]=value2

又比如 var valuex=class1["keyx"]

这个是怎样实现的呢?????????????

经过尝试以后发现了this[] 这个神奇的功能

public class Demo
{
     private Dictionary<string, object> values = new Dictionary<string, object>();
     public object this[string key]
     {
         get
         {
            object ret;
            values.TryGetValue(key, out ret);
            return ret;
         }
         set
         {

            if (values.ContainsKey(key))
               values[key] = value;
            else
                    values.Add(key,value);
         }
      }

}

 

 

这样以后就可以直接进行 new了一个Demo 对象以后 直接就可以进行

Demo demo=new Demo();
demo["BUAA"]="Hello World";
string helloxxxxx= demo["BUAA"].toString()

是不是方便哇

 

根据我给你的代码,帮我扩展一个swap函数出来#ifndef _RBTREE_H_ #define _RBTREE_H_ /* 红黑树性质 验证方法 1. 节点为红或黑 无需显式检查(由颜色枚举保证) 2. 根节点为黑 在入口函数检查 root->_col == BLACK 3. 叶子节点(NIL)为黑 通过 nullptr 隐式处理(到达空节点时统计) 4. 红色节点不能有红子节点 递归检查父子节点颜色 5. 黑高一致性 对比每条路径的黑色节点数是否等于 refNum */ /* 性质: 1.每个节点要么是红色, 要么就是黑色. 2.根节点必为黑色。 3.叶子节点(NIL)都为黑色,数据keyvalue且为null。 4.红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点)(即父与子节点不可能都是红色) 5.从任意节点出发,到其每个叶子节点(NIL)的路径中包含相同数量的黑色节点 衍生特性: 1.新加入到红黑树的节点为红色节点,如果新加入节点是黑色,会影响性质4。所以新节点是红色影响最小 2.根据性质3判断: 叶子节点(NIL)虽然是null, 但也算是一个有效的颜色节点 3.根据性质4判断: 黑色节点的2个子节点可以为2个红色节点; 也可以是2个黑色节点; 也可以是1红1黑的节点 5.根据性质5判断: 确保没有一条路径会比其他路径长出俩倍 */ #include <type_traits> namespace RBTREE { //红黑树的颜色类型 typedef enum class tagCOLOR : unsigned char//给枚举类型限定字节数,C++11开始支持 sizeof(Color) = 1byte { RED, BLACK }COLOR; /****************************************************************************************************************************/ //红黑树左右孩子的位置类型,主要用作判断当前节点是属于父节点的左孩子还是右孩子 //这样就不用疯狂使用父节点寻址才能得到当前节点的分支方向(左右) typedef enum class tagBELONG : unsigned char//给枚举类型限定字节数,C++11开始支持 sizeof(BELONG) = 1byte { ROOT, LEFT, RIGHT, NIL }BELONG; /****************************************************************************************************************************/ //红黑树节点类 template<class KEY, class VALUE> class RBTreeNode { public: COLOR m_Color; //节点颜色,不是红就是黑. 默认色是红色,黑色会影响性质5 KEY m_Key; //关键值: 查找;比较... 都依靠它 VALUE m_Value; //目标元素 RBTreeNode* m_pParent; //父节点 RBTreeNode* m_pLeft; //左孩子 RBTreeNode* m_pRight; //右孩子 BELONG m_beLong; //节点是属于父节点的左孩子还是右孩子。 static RBTreeNode<KEY, VALUE> NIL; // 静态NIL声明 //默认构造函数:仅供NIL叶子节点创建时使用 RBTreeNode() : m_Color(COLOR::BLACK), //NIL节点默认颜色是: 黑色 m_Key(), //KEY默认构造 m_Value(), //VALUE默认构造 m_pParent(nullptr), //父指针置空 m_pLeft(nullptr), //左指针置空 m_pRight(nullptr), //右指针置空 m_beLong(BELONG::NIL) //设置为叶子节点NIL { } //初始化节点数据 RBTreeNode(const KEY& _Key, const VALUE& _Value) : m_Color(COLOR::RED), //新节点默认颜色是: 红色 m_Key(_Key), //启动KEY的复制构造函数 m_Value(_Value), //启动VALUE的复制构造函数 m_pParent(nullptr), //父指针置空 m_pLeft(nullptr), //左指针置空 m_pRight(nullptr), //右指针置空 m_beLong(BELONG::ROOT) //设置为根节点,插入/删除后会调整 { //强制定义叶子节点为的就是维护红黑树的性质: 2.根据性质3判断: 叶子节点(NIL)虽然是null, 但也算是一个有效的颜色节点 m_pRight = &NIL; //新节点的右边指向叶子节点 m_pLeft = &NIL; //新节点的左边指向叶子节点 NIL.m_pLeft = NIL.m_pRight = NIL.m_pParent = &NIL; //完全自引用 //其实可以直接用nullptr去模拟成NIL节点,下面有2个方案的解析说明: 推荐方案:优先使用实质NIL节点 /* 方案一:使用nullptr表示NIL节点 实现方式 优点 内存效率高 不需要为NIL节点分配额外内存,节省空间。 适合内存敏感场景(如嵌入式系统)。 代码简洁 直接使用nullptr判断,减少间接访问。 例如:if(node->m_pLeft == nullptr) 比 if (node->m_pLeft == m_NIL) 更直观。 性能略优 避免指针解引用(访问实质NIL节点需要一次内存访问)。 缺点 边界条件处理复杂 旋转、删除等操作需要频繁检查nullptr,容易遗漏边界条件。 例如:左旋时需确保node->m_pRight != nullptr。 代码重复 每个操作需重复nullptr检查,可能违反DRY原则。 调试困难 nullptr无法提供调试信息(如NIL节点的颜色、父节点等)。 方案二:使用实质NIL节点 实现方式 优点 统一边界条件处理 所有叶子节点均为m_NIL,简化旋转、删除等操作的逻辑。 例如:左旋时无需检查node->m_pRight是否为空。 代码可维护性强 通过isNIL()方法封装判断逻辑,减少重复代码。 调试时可打印NIL节点的信息(如颜色、父节点)。 符合红黑树理论定义 明确区分内部节点和叶子节点,便于验证红黑树性质。 支持复杂自定义类型 自定义类型的NIL节点可初始化默认值,避免未定义行为。 缺点 内存开销 每个红黑树实例需分配一个NIL节点(通常可忽略)。 初始化复杂度 需确保NIL节点的指针自洽(如m_pLeft = m_pRight = m_pParent = this)。 推荐方案:优先使用实质NIL节点 理由 安全性:避免因nullptr检查遗漏导致的未定义行为(如空指针解引用)。 可维护性:统一处理边界条件,减少代码错误。 调试友好:NIL节点可附加调试信息(如颜色、父节点)。 性能差异极小:现代CPU的缓存机制会抵消单次指针解引用的开销。 */ } //判断当前是否叶子节点 inline bool isNIL()const { return m_beLong == BELONG::NIL; } }; // 类外静态成员定义 template<class KEY, class VALUE> RBTreeNode<KEY, VALUE> RBTreeNode<KEY, VALUE>::NIL; /****************************************************************************************************************************/ //红黑树类 template<class KEY, class VALUE> class RBTree { private: RBTreeNode<KEY, VALUE>* m_pRoot;//红黑树根节点, 性质: 必须为黑色 public: //默认构造函数 RBTree() : m_pRoot(nullptr) //新创建的树,根节点置为空 { } //默认析构函数 ~RBTree() { } //判断是否空树 inline bool IsEmpty()const { return m_pRoot == nullptr; } //向红黑树插入元素 bool Insert(const KEY& _Key, const VALUE& _Value) { RBTreeNode<KEY, VALUE>* pNewNode = new RBTreeNode<KEY, VALUE>(_Key, _Value);//创建一个新节点 if (insert(m_pRoot, pNewNode)) //接入内部insert函数 { return true;//返回true } delete pNewNode;//插入失败,删除新节点 pNewNode = NULL; return false; } //精确查找 VALUE* Find(const KEY& _Key) { RBTreeNode<KEY, VALUE>* pResult = find(_Key); return pResult ? &pResult->m_Value : nullptr; } bool Erase(const KEY& _Key) { RBTreeNode<KEY, VALUE>* pResult = find(_Key); if (pResult) { return erase(pResult); } //查找不到指定key return false; } private: //红黑树的内部函数 // 1. 将红黑树当作一颗二叉查找树,将新节点插入到红黑树中。 // 2. 插入完成后再调整树状态,使其能成为一棵合法的红黑树 bool insert(RBTreeNode<KEY, VALUE>* &_pRoot, RBTreeNode<KEY, VALUE>* _pNewNode) //&_pRoot能够使函数内部直接读写m_pRoot { if (_pNewNode == nullptr)return false; RBTreeNode<KEY, VALUE>* pCursor = _pRoot;//操作游标,一般指当前节点 RBTreeNode<KEY, VALUE>* pPreNode = nullptr;//用作 备份上一级节点.当游标指向NIL叶子节点时,此指针就能直接向上回溯出父节点 BELONG blNIL = BELONG::NIL; //用来判断找到的叶子节点是左孩子或者是右孩子 while (pCursor != nullptr && !pCursor->isNIL())//如果当前节点不为空, 并且不是叶子节点 { pPreNode = pCursor;//备份上一个节点,游标将指向下个节点 if (_pNewNode->m_Key < pCursor->m_Key)//如果新节点的key小于当前节点的key { pCursor = pCursor->m_pLeft;//把左孩子赋值给游标 blNIL = BELONG::LEFT;//最后比较是: 向左操作 continue;//重新循环比较 } else if (_pNewNode->m_Key > pCursor->m_Key)//如果新节点的key大于当前节点的key { pCursor = pCursor->m_pRight;//把右孩子赋值给游标 blNIL = BELONG::RIGHT;//最后比较是: 向右操作 continue;//重新循环比较 } else //那么说明插入的节点已经存在 { return false;//插入失败 } } /*代码执行到此, 只有以下2种情况: 1. m_pRoot是空的 2. 说明游标节点已经指向到: 叶子节点*/ if (pCursor == nullptr)//m_pRoot是空的 { _pRoot = _pNewNode; //当前节点为根节点 _pRoot->m_Color = COLOR::BLACK; //根节点要求绝对黑色 _pRoot->m_beLong = BELONG::ROOT; //设置为根节点 return true; } else if(pCursor->isNIL() && pPreNode)//2.游标指向NIL, 说明已经找到适合插入的节点, 并且父节点不为空 { //判断最后的比较操作 if (blNIL == BELONG::LEFT)//叶子节点是位于左边 { //开始与左节点进行联结 pPreNode->m_pLeft = _pNewNode;//父节点的左孩子设置成这个新节点 _pNewNode->m_pParent = pPreNode;//设置这个新节点的父亲 _pNewNode->m_beLong = BELONG::LEFT;//这新节点是父亲的左孩子 //调整颜色不在此处调整 //联结完成 } else if (blNIL == BELONG::RIGHT)//叶子节点是位于右边 { //开始与右节点进行联结 pPreNode->m_pRight = _pNewNode;//父节点的右孩子设置成这个新节点 _pNewNode->m_pParent = pPreNode;//设置这个新节点的父亲 _pNewNode->m_beLong = BELONG::RIGHT;//这新节点是父亲的右孩子 //调整颜色不在此处调整 //联结完成 } else { //不应该也不可能来到此处,属于异常: 不是左操作,也不是右操作,等于操作已经返回false了 return false; } } else { //不应该来到此处,属于异常: 游标指向是叶子节点, 但pPreNode是空,这并不可能发生的事 return false; } //代码执行到此: 需要调整颜色调整树结构了, 审查当前结构的合法性 //设置插入目标节点的颜色为: 红色. 插入新节点为红色对红黑树的性质5影响最小 //_pNewNode->m_Color = Color::RED;//节点初始化已经是红色,无须重复设置 //插入新节点后, 重新修正为一颗平衡二叉树 insert_fix(_pNewNode); ////////// //修正完成后就是一棵标准的: 红黑树 // // return true; // } // // /******************************************开始解析说明 insert_fix() 函数修复红黑树过程******************************** * 红黑树插入修正函数 * * 在向红黑树中插入节点之后(失去平衡),再调用该函数; * 目的是将它根据颜色调整重新塑造成一颗红黑树。 * * 参数说明: * _pRoot 红黑树的根节点 * _pNewNode 插入的新节点 */ /* 修正原理 回忆下红黑树的性质: 性质: 1.每个节点要么是红色, 要么就是黑色。 2.根节点必为黑色。 3.叶子节点(NIL)都为黑色,数据keyvalue且为null。 4.红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点)(即父与子节点不可能都是红色) 5.从任意节点出发,到其每个叶子节点(NIL)的路径中包含相同数量的黑色节点 衍生特性: 1.新加入到红黑树的节点为红色节点,如果新加入节点是黑色,会影响性质4。所以新节点是红色影响最小 2.根据性质3判断: 叶子节点(NIL)虽然keyvalue是null, 但也算是一个有效的颜色节点 3.根据性质4判断: 黑色节点的2个子节点可以为2个红色节点。也可以是2个黑色节点,但必须是叶子节点(NIL)(左右树不可能存在有效的黑色节点) 4.根据性质4判断: 黑色节点的2个子点也可以是1个红色节点,一个黑色节点(叶子节点NIL)(左右树不可能存在有效的黑色节点) 5.根据性质5判断: 确保没有一条路径会比其他路径长出俩倍 ************************************************************************** 总结插入新节点可能出现的情景,并给出处理方案: 情景1: 插入的节点的父节点是黑色 情景1处理方案:无需任何处理 情景2:插入的节点的父节点是红色(父子节点均为红色,需修正) 根据叔叔节点去拆分3种分支情景: 情景2.1: 叔叔节点是存在,并且是红色 情景2.1处理方案: 将父节点设置成黑色; 将叔叔节点设置成黑色; 将祖父节点设置成红色; 将祖父节点设置成当前节点,继续while循环向上修正 情景2.2: 叔叔节点不存在或者叔叔节点是黑色, 并且插入的节点的父节点是属于其祖父节点的左孩子(叔叔是右孩子) 根据情景2.2去拆分2种分支情景: 情景2.2.1: 插入节点是其父节点的右孩子(内侧插入) 情景2.2.1处理方案: 将当前节点的父节点左旋操作后得到情景2.2.2 处理情景2.2.2 情景2.2.2: 插入节点是其父节点的左孩子(外侧插入) 情景2.2.2处理方案: 将父亲节点设置为黑色 将祖父节点设置成红色 将祖父节点进行右旋操作 情景2.3: 叔叔节点不存在或者叔叔节点是黑色, 并且插入节点的父节点是属于其祖父节点的右孩子(叔叔是左孩子) 根据情景2.3去拆分2种分支情景: 情景2.3.1: 插入的节点是其父节点的左孩子(外侧插入) 情景2.3.1处理方案: 将当前节点的父节点右旋操作后得到情景2.3.2 处理情景2.3.2 情景2.3.2: 插入的节点是其父节点的右孩子(内侧插入) 情景2.3.2处理方案: 将父新节点设置成黑色 将祖父节点设置成红色 将祖父节点进行左旋操作 */ bool insert_fix(RBTreeNode<KEY, VALUE>* _pNewNode) { if (!_pNewNode)return false; RBTreeNode<KEY, VALUE>* pParent = _pNewNode->m_pParent; //取得父节点 RBTreeNode<KEY, VALUE>* pGrandfather = nullptr;//取出祖父节点 RBTreeNode<KEY, VALUE>* pUncle = nullptr; //用作储存叔叔节点 // 情景1: 插入的节点的父节点是黑色 // 情景1处理方案:无需任何处理 if (pParent && pParent->m_Color == COLOR::BLACK)return true;//情景1处理完成 if (!pParent)//说明已经到达根节点了 { if (_pNewNode->m_beLong == BELONG::ROOT) { _pNewNode->m_Color = COLOR::BLACK;//根节点强制黑色 return true; } return false; } do { //这是情景2: 插入的新节点的父亲是红色的,违反红黑树性质4: //4. 红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点)(即父与子节点不可能都是红色) pGrandfather = pParent->m_pParent;//取出祖父节点 if (pGrandfather)//祖父节点是有效的 { //如果父亲是左孩子,那么叔叔肯定是祖父的右孩子。否则父亲是右孩子,那么叔叔就是左孩子 pUncle = pParent->m_beLong == BELONG::LEFT ? pGrandfather->m_pRight : pParent->m_beLong == BELONG::RIGHT ? pGrandfather->m_pLeft : nullptr;//取出叔叔节点 if (pUncle == nullptr) { //叔叔节点居然提取不到,不可能的,说明结构有异常 throw("红黑树结构异常: 颜色持衡过程发现->取得叔叔节点失败, 父亲节点居然是NIL"); } //开始检查叔叔节点颜色 if (pUncle->m_Color == COLOR::RED)//叔叔节点是红色: 这是情景2.1 { //情景2.1修正方案: 颜色持衡 //将P设置为黑色 //将U设置为黑色 //将G设置为红色 //将G设置成当前节点继续while循环向上判断 pParent->m_Color = COLOR::BLACK;//将P设置为黑色 pUncle->m_Color = COLOR::BLACK; //将U设置为黑色 pGrandfather->m_Color = COLOR::RED;//将G设置为红色 return insert_fix(pGrandfather);//将G设置成当前节点继续递归循环向上判断 } else if(pUncle->m_Color == COLOR::BLACK)//叔叔节点是黑色: 这是情景2.2或者情景2.3 { if (pParent->m_beLong == BELONG::LEFT)//父亲是个左孩子,触发情景2.2 { if (!_pNewNode) { throw("触发情景2.2: 插入节点为空"); } if (_pNewNode->m_beLong == BELONG::RIGHT)//如果插入节点是其父亲的右孩子: 触发情景 2.2.1 { pParent = left_rotate(pParent);//对父亲进行左旋操作得到情景2.2.2 if (!pParent)throw("红黑树结构异常: 触发情景2.2.1时左旋失败"); _pNewNode = pParent->m_pLeft; //左旋后, 插入节点和父亲交换成功了。 return insert_fix(_pNewNode);//重新递归进入情景: 2.2.2 } else if (_pNewNode->m_beLong == BELONG::LEFT)//如果插入节点是其父亲的左孩子: 触发情景2.2.2 { pParent->m_Color = COLOR::BLACK;//将P设置成黑色 pGrandfather->m_Color = COLOR::RED;//将G设置成红色 pParent = right_rotate(pGrandfather);//对G进行右旋操作 return true;//情景2.2的所有场景解析完成 } //进入到此处代码说明 新插入节点是ROOT,NIL, else已经不可能了,因为insert_fix的上层是insert对pNewNode封装好了 } else if (pParent->m_beLong == BELONG::RIGHT)//父亲是个右孩子,触发情景2.3 { if (!_pNewNode) { throw("触发情景2.3: 插入节点为空"); } if (_pNewNode->m_beLong == BELONG::LEFT)//如果插入的节点是其父亲的左孩子: 触发情景2.3.1 { pParent = right_rotate(pParent);//对父亲进行右旋操作得到情景2.3.2 if(!pParent)throw("红黑树结构异常: 触发情景2.3.1时右旋失败"); _pNewNode = pParent->m_pRight; //右旋后,插入节点和父亲交换成功了 return insert_fix(_pNewNode);//递归 进入情景: 2.3.2 } else if (_pNewNode->m_beLong == BELONG::RIGHT)//如果插入节点是其父亲的右孩子: 触发情景2.3.2 { pParent->m_Color = COLOR::BLACK;//将P设置成黑色 pGrandfather->m_Color = COLOR::RED;//将G设置成红色 pParent = left_rotate(pGrandfather);//对G进行左旋操作 return true;//情景2.3的所有场景解析完成 } //进入到此处代码说明 新插入节点是ROOT,NIL, else已经不可能了,因为insert_fix的上层是insert对pNewNode封装好了 } else if (pParent->m_beLong == BELONG::ROOT) { //插入节点红色,父节点红色才会进入情景2.2-2.3,但父亲如果是根节点Root,那么之前这个红黑树就是不合法了 //因为根节点永远是黑色,所以其实能进入到此处也是异常了。 //pParent->m_Color = COLOR::BLACK;//无条件把根节点设置为黑色 //return true;//已经while到根节点Root了 throw("红黑树结构异常: 插入红色新节点,父节点也是红色,但父节点居然是个根节点,红色的根节点是异常的"); } else { //基本不可能进入到此处,因为叶子节点永远是黑色的 throw("红黑树结构异常: 插入红色新节点,父节点也是红色,但父节点居然是个叶子节点"); } } //else 基本不可能的,因为红黑树性质: 节点不是红就是黑, 不可能进入else了 } else//祖父节点是无效的: 说明只有一种情况:当前的_pParent节点是根节点Root { if (pParent->m_beLong == BELONG::ROOT)//当前父节点是根节点Root { pParent->m_Color = COLOR::BLACK;//无条件把根节点设置为黑色 return true;//已经while到根节点Root了 } else { //祖父节点不存在, 父节点又不是根节点,说明结构异常了 throw("红黑树结构异常: 颜色持衡过程发现->祖父节点为空, 但父节点又不是根节点Root,这情况不应该发生."); } } } while (pParent); return false; } //进行左旋操作 RBTreeNode<KEY, VALUE>* left_rotate(RBTreeNode<KEY, VALUE>* _pTarget) { if (!_pTarget)return nullptr; if (_pTarget->isNIL()) { throw("左旋异常: 目标是个NIL, 叶子节点不能左旋操作"); } RBTreeNode<KEY, VALUE>* pParent = _pTarget->m_pParent; //取出目标的父节点 RBTreeNode<KEY, VALUE>* pRight = _pTarget->m_pRight;//备份目标的右孩子 RBTreeNode<KEY, VALUE>* pTmp = nullptr;//临时操作使用 BELONG beLong = _pTarget->m_beLong;//备份目标的 左/右孩子属性 if (pRight->isNIL()) { throw("左旋异常: 目标的右孩子是NIL, NIL不可能作为父节点的"); } pTmp = _pTarget->m_pRight = pRight->m_pLeft;//重定向右孩子到备份pRight的左孩子 pRight->m_pLeft = nullptr;//把备份的pRight的左孩子断开,因为左孩子已经被目标节点重定向占用了 if (pTmp->isNIL() == false)//如果新定向的右孩子不是NIL叶子节点 { pTmp->m_beLong = BELONG::RIGHT;//这个新孩子是从备份的pRight左边取过来的变成右孩子 pTmp->m_pParent = _pTarget;//把这个新右孩子的父亲设置是目标节点 } //else //新的右孩子是个NIL叶子节点,不用设置NIL属性 pTmp = nullptr;//置空,避免后面误操作 pRight->m_pLeft = _pTarget;//重新设置备份pRight的左孩子为目标节点 _pTarget->m_pParent = pRight;//重设置目标的父亲为pRight _pTarget->m_beLong = BELONG::LEFT;//此时目标就是pRight的左孩子 if (pParent == nullptr)//左旋的目标没有父节点,说明左旋的目标是一个根节点 { if (beLong != BELONG::ROOT)//如果成立,说明之前红黑树结构异常 { //左旋目标没有父节点并且不是根节点,异常了 throw("左旋异常: 目标没有父节点并且也没有根节点的标记"); } pRight->m_beLong = beLong;//设置Root pRight->m_Color = COLOR::BLACK;//根节点必然为黑 pRight->m_pParent = nullptr;//根节点没有父亲 m_pRoot = pRight;//根节点已经发生变化 } else { pRight->m_beLong = beLong;//设置备份pRight的孩子属性 pRight->m_pParent = pParent;//设置备份pRight的父亲 if (beLong == BELONG::LEFT)//左旋目标原来是一个左孩子 { pParent->m_pLeft = pRight; } else//左旋目标原来是一个右孩子 { pParent->m_pRight = pRight; } } return pRight; } //进行左旋操作 RBTreeNode<KEY, VALUE>* right_rotate(RBTreeNode<KEY, VALUE>* _pTarget) { if (!_pTarget)return nullptr; if (_pTarget->isNIL()) { throw("右旋异常: 目标是个NIL, 叶子节点不能右旋操作"); } RBTreeNode<KEY, VALUE>* pParent = _pTarget->m_pParent; //取出目标的父节点 RBTreeNode<KEY, VALUE>* pLeft = _pTarget->m_pLeft;//备份目标的左孩子 RBTreeNode<KEY, VALUE>* pTmp = nullptr;//临时操作使用 BELONG beLong = _pTarget->m_beLong;//备份目标的 左/右孩子属性 if (pLeft->isNIL()) { throw("右旋异常: 目标的左孩子是NIL, NIL不可能作为父节点的"); } pTmp = _pTarget->m_pLeft = pLeft->m_pRight;//重定向左孩子到备份pLeft的右孩子 pLeft->m_pRight = nullptr;//把备份的pLeft的右孩子断开,因为该右孩子已经被目标节点重定向占用了 if (pTmp->isNIL() == false)//如果新定向的左孩子不是NIL叶子节点 { pTmp->m_beLong = BELONG::LEFT;//这个新孩子是从备份的pLeft右边取过来的变成左孩子的 pTmp->m_pParent = _pTarget;//把这个新左孩子的父亲设置是目标节点 } //else //新的左孩子是个NIL叶子节点,不用设置NIL属性 pTmp = nullptr;//置空,避免后面误操作 pLeft->m_pRight = _pTarget;//重新设置备份pLeft的右孩子为目标节点 _pTarget->m_pParent = pLeft;//重设置目标的父亲为pLeft _pTarget->m_beLong = BELONG::RIGHT;//此时目标就是pLeft的右孩子 if (pParent == nullptr)//右旋的目标没有父节点,说明右旋的目标是一个根节点 { if (beLong != BELONG::ROOT)//如果成立,说明之前红黑树结构异常 { //右旋目标没有父节点并且不是根节点,异常了 throw("右旋异常: 目标没有父节点并且也没有根节点的标记"); } pLeft->m_beLong = beLong;//设置Root pLeft->m_Color = COLOR::BLACK;//根节点必然为黑 pLeft->m_pParent = nullptr;//根节点没有父亲 m_pRoot = pLeft;//根节点已经发生变化 } else { pLeft->m_beLong = beLong;//设置备份pLeft的孩子属性 pLeft->m_pParent = pParent;//设置备份pLeft的父亲 if (beLong == BELONG::LEFT)//右旋目标原来是一个左孩子 { pParent->m_pLeft = pLeft; } else//左旋目标原来是一个右孩子 { pParent->m_pRight = pLeft; } } return pLeft; } // 精确查找(返回节点指针,未找到返回nullptr) RBTreeNode<KEY, VALUE>* find(const KEY& key) const { RBTreeNode<KEY, VALUE>* pCurrent = m_pRoot; while (pCurrent && !pCurrent->isNIL()) { if (key == pCurrent->m_Key) { return pCurrent; } else if (key < pCurrent->m_Key) { pCurrent = pCurrent->m_pLeft; } else { pCurrent = pCurrent->m_pRight; } } return nullptr; } //删除操作 bool erase(RBTreeNode<KEY, VALUE>* _pTarget) { if (!_pTarget)return false; RBTreeNode<KEY, VALUE>* pParent = _pTarget->m_pParent; RBTreeNode<KEY, VALUE>* pBrother = nullptr; if (_pTarget->m_Color == COLOR::RED)//场景1:被删除节点是红色 { return remove_node_red(_pTarget);//转入场景1函数独立处理 } else//被删除的节点是黑色 { if (!pParent) { //没有父亲,删除的节点是根节点 return false; } pBrother = _pTarget->m_beLong == BELONG::LEFT ? pParent->m_pRight : pParent->m_pLeft; if (pBrother->m_Color == COLOR::RED)//场景2:被删除节点是黑色,并且兄弟是红色 { } else//场景3:被删除节点是黑色,并且兄弟是黑色 { } } } bool remove_node_red(RBTreeNode<KEY, VALUE>* _pTarget) { RBTreeNode<KEY, VALUE>* pParent = _pTarget->m_pParent;//红节点必然拥有父节点的,没有父亲说明是根节点,红色根节点? if (_pTarget->m_pLeft->isNIL() && _pTarget->m_pRight->isNIL()) { //场景1.1 if (_pTarget->m_beLong == BELONG::LEFT)//删除的目标是个左孩子 { pParent->m_pLeft = _pTarget->m_pLeft;//把父亲的左孩子定向到NIL节点 } else//删除的目标是右孩子 { pParent->m_pRight = _pTarget->m_pRight;//把父亲的右孩子定向到NIL节点 } _pTarget->m_pParent = nullptr;//和父亲正式断开联结 delete _pTarget; //删除目标节点 _pTarget = nullptr; return true; } else//2个子节点都是黑色: 红节点下面不可能只有一个黑色节点的 { //场景1.2 } return false; } }; } #endif // !_RBTREE_H_
最新发布
07-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值