赞
踩
目录
- // 节点的颜色
- 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; // 节点的颜色
- };
1)按照二叉搜索的树规则插入新节点
- template<class ValueType>
- class RBTree
- {
- //……
- bool Insert(const ValueType& data)
- {
- PNode& pRoot = GetRoot();
- if (nullptr == pRoot)
- {
- pRoot = new Node(data, BLACK);
- // 根的双亲为头节点
- pRoot->_pParent = _pHead;
- _pHead->_pParent = pRoot;
- }
- else
- {
- // 1. 按照二叉搜索的树方式插入新节点(不会的话可以参照我上篇讲AVL树的博客)
- // 2. 检测新节点插入后,红黑树的性质是否造到破坏,
- // 若满足直接退出,否则对红黑树进行旋转着色处理
- }
- // 根节点的颜色可能被修改,将其改回黑色
- pRoot->_color = BLACK;
- _pHead->_pLeft = LeftMost();
- _pHead->_pRight = RightMost();
- return true;
- }
- private:
- PNode& GetRoot() { return _pHead->_pParent; }
- // 获取红黑树中最小节点,即最左侧节点
- PNode LeftMost();
- // 获取红黑树中最大节点,即最右侧节点
- PNode RightMost();
- private:
- PNode _pHead;
- };
2)检测新节点插入后,红黑树的性质是否造到破坏
● 情况一: cur为红,p为红,g为黑,u存在且为红
● 情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑
- bool Insert(const ValueType& data)
- {
- //按照搜索二叉树规则进行插入(不会的可以去看我前面所讲的博客)
- // ...
- // 新节点插入后,如果其双亲节点的颜色为空色,则违反性质3:不能有连在一起的红色结点
- while (pParent && RED == pParent->_color)
- {
- // 注意:grandFather一定存在
- // 因为pParent存在,且不是黑色节点,则pParent一定不是根,则其一定有双亲
- PNode grandFather = pParent->_pParent;
- // 先讨论左侧情况
- if (pParent == grandFather->_pLeft)
- {
- PNode unclue = grandFather->_pRight;
- // 叔叔节点存在,且为红
- if (unclue && RED == unclue->_color)
- {
- pParent->_color = BLACK;
- unclue->_color = BLACK;
- grandFather->_color = RED;
- pCur = grandFather;
- pParent = pCur->_pParent;
- }
- else
- {
- // 叔叔节点不存在,或者叔叔节点存在且为黑
- if (pParent->_left == pCur)
- {
- //单旋
- pParent->_col = BLACK;
- grandFather->_col = RED;
- _RotateRight(grandFather);
- }
- else
- {
- //双旋 先左再右
- _RotateLeft(pParent);
- pCur->_col = BLACK;
- grandFather->_col = RED;
- _RotateRight(grandFather);
- }
- break;
- }
- }
- else
- {
- // 右侧请尝试自己动手完成
- }
- }
- // ...
- }
- public:
- bool IsRBTree()
- {
- //根节点一定为黑节点
- if (_root->_col == RED)
- {
- cout << "根节点为红节点" << endl;
- return false;
- }
-
- int DefNum = 0;
- //为了判断每条路径上的黑节点是否相等
- //这里可以任意记录一条路径上(这里记录的是最左侧路径)黑节点的个数
- //并传值下去进行判断使用
- Node* cur = _root;
- while (cur)
- {
- if (cur->_col == BLACK)
- {
- DefNum++;
- }
-
- cur = cur->_left;
- }
-
- return _Check(_root,0,DefNum);
- }
-
- private:
- bool _Check(Node* root,int BlackNum,int DefNum)
- {
- if (root == nullptr)
- {
- if (BlackNum != DefNum)
- //这里每条路径递归到最后判断黑节点总数是否相等
- {
- cout << BlackNum << "|" << DefNum << endl;
- cout << "存在黑色节点数量不相等的路径" << endl;
- return false;
- }
- return true;
- }
-
- //节点为红节点的话其在这一部已经判定一定不是根节点,那么一定有其父节点
- if (root->_col == RED && root->_parent->_col == RED)
- //因为一个孩子最多有两个孩子
- //从上往下判断是否为连续的红节点是比较复杂的
- //我们可以从下网上判断,因为一个孩子只有一个父亲
- {
- cout <<root->_kv.first<<"->存在连续的两个红节点" << endl;
- return false;
- }
-
- if (root->_col == BLACK)
- {
- BlackNum++;
- }
-
- return _Check(root->_left,BlackNum,DefNum)
- && _Check(root->_right,BlackNum,DefNum);
- }
如果以上内容对你有帮助不妨点赞支持一下,以后还会分享更多编程知识,我们一起进步。
最后我想讲的是,据说点赞的都能找到漂亮女朋友❤
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。