红黑树的实现 以及加迭代器
来源:互联网 发布:怎么查手机网络制式 编辑:程序博客网 时间:2024/05/17 04:54
在说红黑树之前,我们先来认识一下它:
首先强调一点:红黑树也是二叉搜索树。那么它就满足二叉搜索树的性质,除此之外,他还有几个比较特殊的性质,了解这些,有助于我们后面的分析
性质:
1、红黑树所有的节点都有颜色(红或黑)
2、红黑树的根结点是黑色的
3、红黑树的两个红色节点不能相连
4、红黑树的每一条链的黑节点的个数相同
5、所有空的节点都是黑色的
知道了这些之后开始进入红黑树的创建:
显然这就是红黑树的插入操作的编写了,那么要想将一个节点插入红黑树中,首先你得判断红黑树是不是空的,如果是空的,那么直接就可以插入;不是空的,那么得找插入位置,然后再插入,这一点和二叉搜索树的插入是一样的。不过需要注意,最后把根结点置成黑色的
但是之后呢?
插入的节点我们都默认为红色的,但是性质3说,红色的节点不能相链,如果,之后我们不管的话,性质3肯定不会满足的,所以我们需要对红黑树进行调解,让其满足这些性质。那么我们就需要分情况讨论了,我们重点分析一下,两个红色节点相链的情况怎么处理。
总共可以分为3种情况:
情况一:
双亲结点为红色,祖先结点为黑色, 叔叔节点存在,且为红色
其实这个图里包含了四种情况,我只是将其中的一种情况中的转化后的形式画了出来,其他的也一样。
情况二:
双亲结点为红色,祖先结点为黑色,叔叔节点不存在或存在为黑色
这种情况是:双亲在祖先节点的左的同时pCur在双亲的左;或是双亲在祖先节点的右的同时,pCur在双亲的右。
这样我们就可以进行单旋处理,根据情况调用左单旋还是右单旋。
情况三:
双亲结点为红色,祖先结点为黑色,叔叔节点不存在或存在为黑色
这个和情况二是互补的,情况二中剩下的都是不能单旋直接处理的,那么就需要双旋,图中画的是左右双旋,先左旋之后,我们发现,和情况二的一样,那么代码中这一块就可以放在一起处理。
不过,这里需要注意一点,就是,左旋之后只想pCur变成了双亲,而parent变成了孩子,所以,在第一次旋转之后先对这两个指针进行交换,在进行第二次旋转。
最后将插入写完之后,我们可以写一个函数来测试一下这个是不是红黑树,这个其实也是对红黑树的性质的检验。其中重点验证性质3和性质4。那么我们来分析一下这步骤:
1、判断这个树是不是空树,是的话,直接返回true
2、验证性质2,判断根结点的颜色是不是黑色的,是,返回true
3、要验证性质三,得遍历整个树,而性质4的验证也要这莫做,那么我们将这两个一起验证。那么首先我们得求出一条链的黑色节点的个数,并将其保存起来,再递归遍历左右子树,验证。
//无迭代器template<class K, class V>class RBTree{ typedef RBTreeNode<K, V> Node;public: RBTree() :_pRoot(NULL) {} // 首先:搜索树 bool Insert(const K& key, const V& value) { if (_pRoot == NULL) { _pRoot = new Node(key, value); _pRoot->_color = BLACK; return true; } //找插入位置 Node*pCur = _pRoot; Node*parent = NULL; while (pCur) { if (key < pCur->_key) { parent = pCur; pCur = pCur->_pLeft; } else if (key>pCur->_key) { parent = pCur; pCur = pCur->_pRight; } else return false; } //插入 pCur = new Node(key, value); if (key < parent->_key) parent->_pLeft = pCur; else parent->_pRight = pCur; pCur->_pParent = parent;//注意,不要遗漏了。。。 //看红黑树是否还满足其性质(分情况讨论) while (_pRoot!=pCur && pCur->_pParent->_color == RED) { Node* gf = parent->_pParent;//保存双亲的双亲 //gf肯定存在,因为,如果不存在,那么parent就是根结点,是黑色的,不会进入这个循环 //双亲在左,叔叔(存在的话)在右 if (gf->_pLeft == parent) { Node*uncle = gf->_pRight; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pRight == pCur) { _RotateL(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateR(gf); } } else//双亲在右 { Node*uncle = gf->_pLeft; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pLeft == pCur) { _RotateR(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateL(gf); } } } _pRoot->_color = BLACK; return true; } void InOrder() { cout << "InOrder: "; _InOrder(_pRoot); cout << endl; } //判断是不是红黑树 bool CheckRBTree() { if (_pRoot == NULL) return true; if (_pRoot->_color == RED)//违反性质2“根结点为黑色” return false; size_t blackcount = 0;//统计一条链中黑色结点的数量 Node* pCur = _pRoot; while (pCur) { if (pCur->_color == BLACK) blackcount++; pCur = pCur->_pLeft;//这里以最左边的那一条链为例 } //验证性质4“每条链上的黑色结点都相等”,顺便验证性质3“红色结点不能相连” return _CheckRBTree(_pRoot, blackcount, 0); }private: //判断是不是红黑树(递归) //k用来统计每一条链上的黑色结点的个数,但是不能给成引用,否则,再次统计下一条链的时候,就不会更新 bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) { if (pRoot == NULL) return true; if (pRoot->_color == BLACK) k++; Node* parent = pRoot->_pParent; if (parent && parent->_color == RED && pRoot->_color == RED)//违反性质3 return false; if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL) { if (k != blackCount)//违反性质4 return false; } return _CheckRBTree(pRoot->_pLeft, blackCount, k) && _CheckRBTree(pRoot->_pRight, blackCount, k); } //左旋 void _RotateL(Node* parent) { Node* subR = parent->_pRight; Node* subRL = subR->_pLeft;//有可能不存在 parent->_pRight = subRL; if (subRL) subRL->_pParent = parent; subR->_pLeft = parent; Node* gparent = parent->_pParent;//保存parent的双亲 parent->_pParent = subR; if (gparent == NULL)//parent是根结点 _pRoot = subR; else if (gparent->_pLeft == parent) gparent->_pLeft = subR; else gparent->_pRight = subR; subR->_pParent = gparent;//第三个 } //右旋 void _RotateR(Node* parent) { Node*subL = parent->_pLeft; Node*subLR = subL->_pRight; parent->_pLeft = subLR; if (subLR) subL->_pParent = parent; subL->_pRight = parent; Node*gparent = parent->_pParent; parent->_pParent = subL; subL->_pParent = gparent; if (gparent == NULL) _pRoot = subL; else if (gparent->_pLeft == parent) gparent->_pLeft = subL; else gparent->_pRight = subL; } //中序遍历 void _InOrder(Node* pRoot) { if (pRoot) { _InOrder(pRoot->_pLeft); cout << pRoot->_key << " "; _InOrder(pRoot->_pRight); } } //获取最小节点 Node* _GetMinNode() { Node* pCur = _pRoot; Node*parent = NULL; while (pCur) { parent = pCur; pCur = pCur->_pLeft; } return parent; } //获取最大节点 Node* _GetMaxNode() { Node* pCur = _pRoot; Node*parent = NULL; while (pCur) { parent = pCur; pCur = pCur->_pRight; } return parent; }private: Node* _pRoot;};#endifvoid TestRBTree(){ int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 }; RBTree<int, int> t; for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx) t.Insert(a[idx], idx); t.InOrder(); if (t.CheckRBTree()) { cout << "是红黑树" << endl; } else { cout << "不是红黑树" << endl; }}
迭代器中给出了什么操作:
Self& operator++();Self operator++(int);Self& operator--();Self operator--(int);Ref operator*();//这里的Ref是我自己通过模板类给出的类型const Ref operator*()const ;Pointer operator->();const Pointer operator->()const;
这里重点就是自增和自减的操作,我们知道红黑是是二叉搜索树,那么他的中序遍历是有序的,所以,在迭代器下,一个节点的下一个节点是它右子树的最左边的节点;同样,一个节点的上一个节点是他左子树的最右边的节点。
但是这里总有一些例外的情况,如:一个结点右子树没有左节点那么怎么处理,或是左子树没有右节点呢?
对于这两种情况我们需要特别处理,那么以第二个图来说,这是右子树没有左节点的情况,也就是自增的情况,那么我们需要将其双亲保存起来,然后向上面遍历们直到找到一个其左孩子存在为止,这时候,其就是要找的节点。
同样的,自减也是这样,不过这里需要要遭注意一个特殊的地方,就是,在头结点的位置,我们要是进行自减的话,按理说,应该是到key最大的位置,但是,我们的代码中,并不适用这个,所以,我们需要拿出来单独处理。
void _Increment() { //找右子树的最左边的节点 if (_pNode->_pRight) { _pNode = _pNode->_pRight; while (_pNode->_pLeft) _pNode = _pNode->_pLeft; } //特殊情况 else { Node* parent = _pNode->_pParent; while (parent->_pRight == _pNode) { _pNode = parent; parent = parent->_pParent; } if (parent->_pRight != _pNode) _pNode = parent; } } void _Decrement() { //头结点的情况:自减之后到key最大的结点 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* parent = _pNode->_pParent; while (parent->_pLeft == _pNode) { _pNode = parent; parent = parent->_pParent; } _pNode = parent; } }
下面是完整的代码:
#include<iostream>using namespace std;enum COLOR{ RED, BLACK };template<class K, class V>struct RBTreeNode{ RBTreeNode(const K& key = K(), const V& value = V(), const COLOR& color = RED) :_pLeft(NULL) , _pRight(NULL) , _pParent(NULL) , _key(key) , _value(value) , _color(color) {} RBTreeNode<K, V>* _pLeft; RBTreeNode<K, V>* _pRight; RBTreeNode<K, V>* _pParent; K _key; V _value; COLOR _color; //结点的颜色,初始值为红色};#if 0template<class K, class V, class Ref, class Pointer>class RBTreeIterator{ typedef RBTreeNode<K, V> Node; typedef RBTreeIterator<K, V, Ref, Pointer> Self;public: RBTreeIterator() : _pNode(NULL) {} RBTreeIterator(Node* pNode) : _pNode(pNode) {} RBTreeIterator(RBTreeIterator& it) : _pNode(it._pNode) {} Self& operator++() { _Increment(); return *this; } Self operator++(int) { Self temp = *this; _Increment(); return temp; } Self& operator--() { _Decrement(); return *this; } Self operator--(int) { Self temp = *this; _Decrement(); return temp; } Ref operator*() { return _pNode->_key; } const Ref operator*()const { return _pNode->_key; } Pointer operator->() { return &(operator*()); } const Pointer operator->()const { return &(operator*()); } bool operator==(const Self& it) { return _pNode == it._pNode; } bool operator!=(const Self& it) { return _pNode != it._pNode; }protected: void _Increment() { //找右子树的最左边的节点 if (_pNode->_pRight) { _pNode = _pNode->_pRight; while (_pNode->_pLeft) _pNode = _pNode->_pLeft; } //特殊情况 else { Node* parent = _pNode->_pParent; while (parent->_pRight == _pNode) { _pNode = parent; parent = parent->_pParent; } if (parent->_pRight != _pNode) _pNode = parent; } } void _Decrement() { //头结点的情况:自减之后到key最大的结点 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* parent = _pNode->_pParent; while (parent->_pLeft == _pNode) { _pNode = parent; parent = parent->_pParent; } _pNode = parent; } }protected: Node* _pNode;};template<class K, class V>class RBTree{ typedef RBTreeNode<K, V> Node;public: typedef RBTreeIterator<K, V, K&, K*> Iterator;public: RBTree() :_size(0) { _pHead = new Node(K(), V()); _pHead->_pLeft = _pHead; _pHead->_pRight = _pHead; _pHead->_pParent = NULL; _pHead->_color = RED; } Iterator Begin() { return Iterator(_pHead->_pLeft); } Iterator End() { return Iterator(_pHead);//注意end的位置,不是最大的key所在结点 } bool Empty()const { return _size == 0; } size_t Size()const { return _size; } Iterator Find(const K& key) { Iterator it = Begin(); while (it != End()) { if (key == *it) return it; else ++it; } } // 首先:搜索树 bool Insert(const K& key, const V& value) { Node* pRoot = _GetRoot(); if (pRoot == NULL) { Node* pRoot = new Node(key, value); pRoot->_pParent = _pHead; _pHead->_pParent = pRoot; pRoot->_color = BLACK; _size++; return true; } //找插入位置 Node*pCur = pRoot; Node*parent = NULL; while (pCur) { if (key < pCur->_key) { parent = pCur; pCur = pCur->_pLeft; } else if (key>pCur->_key) { parent = pCur; pCur = pCur->_pRight; } else return false; } //插入 pCur = new Node(key, value); if (key < parent->_key) parent->_pLeft = pCur; else parent->_pRight = pCur; _size++; pCur->_pParent = parent;//注意,不要遗漏了。。。 //看红黑树是否还满足其性质(分情况讨论) while (pRoot != pCur && parent->_color == RED)//这个条件很重要 { Node* gf = parent->_pParent;//保存双亲的双亲 //双亲在左,叔叔(存在的话)在右 if (gf->_pLeft == parent) { Node*uncle = gf->_pRight; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pRight == pCur) { _RotateL(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateR(gf); } } else//双亲在右 { Node*uncle = gf->_pLeft; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pLeft == pCur) { _RotateR(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateL(gf); } } } pRoot = _GetRoot();//旋转完成之后要再把根结点获取一遍 pRoot->_color = BLACK; _pHead->_pLeft = _GetMinNode(); _pHead->_pRight = _GetMaxNode(); return true; } void InOrder() { cout << "InOrder: "; _InOrder(_GetRoot()); cout << endl; } //判断是不是红黑树 bool CheckRBTree() { Node* pRoot = _GetRoot(); if (pRoot == NULL) return true; if (pRoot->_color == RED)//违反性质2“根结点为黑色” return false; size_t blackcount = 0;//统计一条链中黑色结点的数量 while (pRoot) { if (pRoot->_color == BLACK) blackcount++; pRoot = pRoot->_pLeft;//这里以最左边的那一条链为例 } //验证性质4“每条链上的黑色结点都相等”,顺便验证性质3“红色结点不能相连” return _CheckRBTree(pRoot, blackcount, 0); }private: //判断是不是红黑树(递归) //k用来统计每一条链上的黑色结点的个数,但是不能给成引用,否则,再次统计下一条链的时候,就不会更新 bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) { if (pRoot == NULL) return true; if (pRoot->_color == BLACK) k++; Node* parent = pRoot->_pParent; if (parent && parent->_color == RED && pRoot->_color == RED)//违反性质3 return false; if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL) { if (k != blackCount)//违反性质4 return false; } return _CheckRBTree(pRoot->_pLeft, blackCount, k) && _CheckRBTree(pRoot->_pRight, blackCount, k); } //左旋 void _RotateL(Node* parent) { Node* subR = parent->_pRight; Node* subRL = subR->_pLeft;//有可能不存在 parent->_pRight = subRL; if (subRL) subRL->_pParent = parent; subR->_pLeft = parent; Node* gparent = parent->_pParent;//保存parent的双亲 parent->_pParent = subR; if (gparent == _pHead)//parent是根结点 { _pHead->_pParent = subR; //注意:这一块的根结点怎么表示 subR->_pParent = _pHead; } else if (gparent->_pLeft == parent) gparent->_pLeft = subR; else gparent->_pRight = subR; subR->_pParent = gparent;//第三个 } //右旋 void _RotateR(Node* parent) { Node*subL = parent->_pLeft; Node*subLR = subL->_pRight; parent->_pLeft = subLR; if (subLR) subL->_pParent = parent; subL->_pRight = parent; Node*gparent = parent->_pParent; parent->_pParent = subL; subL->_pParent = gparent; if (gparent == _pHead) { _pHead->_pParent = subL; subL->_pParent = _pHead; } else if (gparent->_pLeft == parent) gparent->_pLeft = subL; else gparent->_pRight = subL; } //中序遍历 void _InOrder(Node* pRoot) { if (pRoot) { _InOrder(pRoot->_pLeft); cout << pRoot->_key << " "; _InOrder(pRoot->_pRight); } } //获取根结点 Node* &_GetRoot() { return _pHead->_pParent; } //获取最小节点 Node* _GetMinNode() { Node*pRoot = _pHead->_pParent; Node*parent = NULL; while (pRoot) { parent = pRoot; pRoot = pRoot->_pLeft; } return parent; } //获取最大节点 Node* _GetMaxNode() { Node*pRoot = _pHead->_pParent; Node*parent = NULL; while (pRoot) { parent = pRoot; pRoot = pRoot->_pRight; } return parent; }private: Node* _pHead; //头结点 size_t _size; };#else//无迭代器template<class K, class V>class RBTree{ typedef RBTreeNode<K, V> Node;public: RBTree() :_pRoot(NULL) {} // 首先:搜索树 bool Insert(const K& key, const V& value) { if (_pRoot == NULL) { _pRoot = new Node(key, value); _pRoot->_color = BLACK; return true; } //找插入位置 Node*pCur = _pRoot; Node*parent = NULL; while (pCur) { if (key < pCur->_key) { parent = pCur; pCur = pCur->_pLeft; } else if (key>pCur->_key) { parent = pCur; pCur = pCur->_pRight; } else return false; } //插入 pCur = new Node(key, value); if (key < parent->_key) parent->_pLeft = pCur; else parent->_pRight = pCur; pCur->_pParent = parent;//注意,不要遗漏了。。。 //看红黑树是否还满足其性质(分情况讨论) while (_pRoot!=pCur && pCur->_pParent->_color == RED) { Node* gf = parent->_pParent;//保存双亲的双亲 //gf肯定存在,因为,如果不存在,那么parent就是根结点,是黑色的,不会进入这个循环 //双亲在左,叔叔(存在的话)在右 if (gf->_pLeft == parent) { Node*uncle = gf->_pRight; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pRight == pCur) { _RotateL(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateR(gf); } } else//双亲在右 { Node*uncle = gf->_pLeft; if (uncle && uncle->_color == RED) //情况一 { parent->_color = BLACK; uncle->_color = BLACK; gf->_color = RED; //向上更新 pCur = gf; parent = pCur->_pParent; } else //情况二、三(将情况三转化为情况二,再一起处理) { if (parent->_pLeft == pCur) { _RotateR(parent); std::swap(parent, pCur); } gf->_color = RED; parent->_color = BLACK; _RotateL(gf); } } } _pRoot->_color = BLACK; return true; } void InOrder() { cout << "InOrder: "; _InOrder(_pRoot); cout << endl; } //判断是不是红黑树 bool CheckRBTree() { if (_pRoot == NULL) return true; if (_pRoot->_color == RED)//违反性质2“根结点为黑色” return false; size_t blackcount = 0;//统计一条链中黑色结点的数量 Node* pCur = _pRoot; while (pCur) { if (pCur->_color == BLACK) blackcount++; pCur = pCur->_pLeft;//这里以最左边的那一条链为例 } //验证性质4“每条链上的黑色结点都相等”,顺便验证性质3“红色结点不能相连” return _CheckRBTree(_pRoot, blackcount, 0); }private: //判断是不是红黑树(递归) //k用来统计每一条链上的黑色结点的个数,但是不能给成引用,否则,再次统计下一条链的时候,就不会更新 bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) { if (pRoot == NULL) return true; if (pRoot->_color == BLACK) k++; Node* parent = pRoot->_pParent; if (parent && parent->_color == RED && pRoot->_color == RED)//违反性质3 return false; if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL) { if (k != blackCount)//违反性质4 return false; } return _CheckRBTree(pRoot->_pLeft, blackCount, k) && _CheckRBTree(pRoot->_pRight, blackCount, k); } //左旋 void _RotateL(Node* parent) { Node* subR = parent->_pRight; Node* subRL = subR->_pLeft;//有可能不存在 parent->_pRight = subRL; if (subRL) subRL->_pParent = parent; subR->_pLeft = parent; Node* gparent = parent->_pParent;//保存parent的双亲 parent->_pParent = subR; if (gparent == NULL)//parent是根结点 _pRoot = subR; else if (gparent->_pLeft == parent) gparent->_pLeft = subR; else gparent->_pRight = subR; subR->_pParent = gparent;//第三个 } //右旋 void _RotateR(Node* parent) { Node*subL = parent->_pLeft; Node*subLR = subL->_pRight; parent->_pLeft = subLR; if (subLR) subL->_pParent = parent; subL->_pRight = parent; Node*gparent = parent->_pParent; parent->_pParent = subL; subL->_pParent = gparent; if (gparent == NULL) _pRoot = subL; else if (gparent->_pLeft == parent) gparent->_pLeft = subL; else gparent->_pRight = subL; } //中序遍历 void _InOrder(Node* pRoot) { if (pRoot) { _InOrder(pRoot->_pLeft); cout << pRoot->_key << " "; _InOrder(pRoot->_pRight); } } //获取最小节点 Node* _GetMinNode() { Node* pCur = _pRoot; Node*parent = NULL; while (pCur) { parent = pCur; pCur = pCur->_pLeft; } return parent; } //获取最大节点 Node* _GetMaxNode() { Node* pCur = _pRoot; Node*parent = NULL; while (pCur) { parent = pCur; pCur = pCur->_pRight; } return parent; }private: Node* _pRoot;};#endifvoid TestRBTree(){ int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 }; RBTree<int, int> t; for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx) t.Insert(a[idx], idx); t.InOrder(); if (t.CheckRBTree()) { cout << "是红黑树" << endl; } else { cout << "不是红黑树" << endl; }}//void TestIterator()//{// int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };// RBTree<int, int> t;// for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx)// t.Insert(a[idx], idx);// t.InOrder();//// RBTree<int, int>::Iterator it = t.Begin();// while (it != t.End())// {// cout << *it << " ";// ++it;// }//// RBTree<int, int>::Iterator itEnd = t.End();// --itEnd;// cout << *itEnd << endl;//}int main(){ TestRBTree(); //TestIterator(); return 0;}
- 红黑树的实现 以及加迭代器
- 红黑树的介绍以及代码实现(C++)
- socketpair的用途以及实现
- strcpy以及memcpy的实现
- 登录的实现以及sessionout
- socketpair的用途以及实现
- 通讯录的创建以及实现
- RecyclerView 以及 ItemClickListener的实现
- RecyclerView 以及 ItemClickListener的实现
- socketpair的用途以及实现
- Hashmap的原理以及实现
- hashmap的底层以及实现
- 位图的实现以及应用
- 队列的定义以及实现
- libCoAP的源码以及实现
- 分页实现以及访问量的实现
- 红黑树C++实现以及与AVL树的区别
- 位图的实现以及位图的应用
- 在Java项目中引入JSTL的方法
- scrapy爬虫【3】→爬图片
- 【Tensorflow】报错:AttributeError: 'module' object has no attribute 'scalar_summary'
- jdbc连接数据库 实现步骤
- Linux环境MySQL5.7主从同步配置
- 红黑树的实现 以及加迭代器
- Android的第一次见面
- Android LayoutInflater(布局填充器)使用指南
- 游戏策划游戏研发必读经典题文一
- javaee新建server无法选安装的Tomcat进行next
- 11.activiti工作流-开始活动节点
- 注册表
- 【ROS-MoveIt!源码学习】ROS中机器人模型的构建(Build RobotModel)
- React Native启动白屏问题