Insert完善
根据规则4, 新增节点必须为红; 根据规则3, 新增节点之父节点必须为黑.
示例:
(1)插入16(红色)/55(红色), 则既不用旋转, 也不用重新染色
(2)插入82(红色), 则违反了红黑规则, 需要进行动态的调整;
红黑树所需的处理
1.单旋转
新插入的X与其父P都是红色的, 而且X还是G的外部孙子;
2.双旋转
新插入的X与其父P都是红色的, 而且X还是G的内部孙子;
3.还需要处理有两个红色孩子的节点, 将右儿子变成黑色的, 我们只允许左儿子是红色的;方法: 旋转+重新染色
insert完整实现代码:
/**注意带有 ++ 注释的为新添加的代码**/ template <typename Comparable> void RedBlackTree<Comparable>::insert(const Comparable &x) { current = parent = grand = great = header; nullNode->element = x; while (current->element != x) { //让祖父成为曾祖父, 父亲成为祖父, 自己成为父亲 //每个人都长了一辈 great = grand; grand = parent; parent = current; current = (x < current->element) ? current->left : current->right; // ++ //+ 处理1. 如果current节点有两个红孩子 if ((current->left->color == RED) && (current->right->color == RED)) handleReorient( x ); } //如果树中包含相同的元素 if (current != nullNode) throw DuplicateItemException(); current = new Node(x, nullNode, nullNode); if (x < parent->element) parent->left = current; else parent->right = current; // ++ //+ 处理2. 如果新插入的节点破坏了红黑规则, 则还需做一次处理 handleReorient( x ); }
/**自动平衡函数: [1]重新染色 [2]自动旋转 */ template <typename Comparable> void RedBlackTree<Comparable>::handleReorient(const Comparable & item) { // 将current节点染成红色 current->color = RED; // 将current的left和right节点染成黑色 current->left->color = current->right->color = BLACK; // 如果current节点的父节点也是红的 -> 单旋转 or 双旋转 if( parent->color == RED ) { //则将其祖父(爷爷)的颜色染成红色 grand->color = RED; //然后判断新插入的节点是否是内部孙子? //如果是, 则增加一次旋转->构成双旋转 //if注释: 如果该节点小于爷爷, 小于爸爸, 这两种情况不同时满足 //则说明其是爷爷的内孙子 if( (item < grand->element) != (item < parent->element) ) { // 则依grand(祖父)节点进行旋转 parent = rotate( item, grand ); // Start double rotate } // 则依great(曾祖父)节点进行旋转 current = rotate( item, great ); //令当前节点为黑色 current->color = BLACK; } //根节点必须是黑色的 header->right->color = BLACK; // Make root black }
// 自动判断并进行旋转函数 template <typename Comparable> typename RedBlackTree<Comparable>::Node * RedBlackTree<Comparable>::rotate(const Comparable &item, Node *theParent ) { //位于theParent的左子树 if( item < theParent->element ) { //如果为真, 则说明theParent->left有左孩子, //否则, 有右孩子 item < theParent->left->element ? //如果theParent左边有一棵子树, 则以theParent->left //为轴, 向右转 rotateWithLeftChild( theParent->left ) : // LL //如果theParent右边有一棵子树, 则以theParent->left //为轴, 向左转 rotateWithRightChild( theParent->left ) ; // LR return theParent->left; //返回左子树 } else //位于右子树 { //如果为真, 则说明theParent->right有左孩子,往右转 //否则, 有右孩子, 往左转 item < theParent->right->element ? rotateWithLeftChild( theParent->right ) : // RL rotateWithRightChild( theParent->right ); // RR return theParent->right; //返回右子树 } }
测试代码:
int main() { //用NEG_INF来代表负无穷大 const int NEG_INF = -999999; RedBlackTree<int> tree(NEG_INF); tree.insert(50); cout << tree.header->right->element << " " << tree.header->right->nodeColor() << endl; cout << endl; tree.insert(40); cout << tree.header->right->left->element << " " << tree.header->right->left->nodeColor() << endl << endl; //此时需要进行旋转和重新染色 tree.insert(30); cout << tree.header->right->element << " " << tree.header->right->nodeColor() << endl ; cout << tree.header->right->left->element << " " << tree.header->right->left->nodeColor() << endl; cout << tree.header->right->right->element << " " << tree.header->right->right->nodeColor() << endl; return 0; }
//由于需要用到nodeColor成员函数, 因此我们将RedBlackNode类改造如下: template <typename Comparable> class RedBlackNode { friend class RedBlackTree<Comparable>; public: RedBlackNode(const Comparable &theElement = Comparable(), RedBlackNode *theLeft = NULL, RedBlackNode *theRight = NULL, int theColor = RedBlackTree<Comparable>::BLACK) : element(theElement), left(theLeft), right(theRight), color(theColor) {} public: //返回当前节点的颜色, 以作测试 std::string nodeColor() const { return (color == RedBlackTree<Comparable>::BLACK) ? "black" : "red"; } public: Comparable element; RedBlackNode *left; RedBlackNode *right; int color; };
红黑树其他操作
template <typename Comparable> class RedBlackTree { ... bool isEmpty() const; void makeEmpty(); Gref<Comparable> find(const Comparable & x) const; Gref<Comparable> findMin() const; Gref<Comparable> findMax() const; //递归删除所有节点 void reclainMemory(Node *t) const; ... };
//析构函数完善版本 template <typename Comparable> RedBlackTree<Comparable>::~RedBlackTree() { if (!isEmpty()) makeEmpty(); delete nullNode; delete header; }
//红黑树查找:与二叉查找树类似 template <typename Comparable> Gref<Comparable> RedBlackTree<Comparable>::find(const Comparable &x) const { if (isEmpty()) return Gref<Comparable>(); nullNode->element = x; Node *iter = header->right; while (true) { if (x < iter->element) iter = iter->left; else if (x > iter->element) iter = iter->right; //如果 x == iter->element else if (iter != nullNode) return Gref<Comparable>(iter->element) ; else return Gref<Comparable>(); } }
//查找最大值: 一路向右 template <typename Comparable> Gref<Comparable> RedBlackTree<Comparable>::findMax() const { if (isEmpty()) return Gref<Comparable>(); Node *iter = header->right; while (iter->right != nullNode) { // 一直向右走 iter = iter->right; } return Gref<Comparable>(iter->element); }
//查找最小值: 一路向左 template <typename Comparable> Gref<Comparable> RedBlackTree<Comparable>::findMin() const { if (isEmpty()) return Gref<Comparable>(); Node *iter = header->right; while (iter->left != nullNode) { // 一直向左走 iter = iter->left; } return Gref<Comparable>(iter->element); }
template <typename Comparable> bool RedBlackTree<Comparable>::isEmpty() const { if (header->right == nullNode) return true; return false; } template <typename Comparable> void RedBlackTree<Comparable>::makeEmpty() { reclainMemory(header->right); header->right = nullNode; } template <typename Comparable> void RedBlackTree<Comparable>::reclainMemory(Node *t) const { //t == t->left的时候, 是当t==nullNode时 if (t != t->left) { reclainMemory(t->left); reclainMemory(t->right); delete t; } }
Gref设计与实现
//一个包装器: 将指针封装成为引用 template <typename Object> class Gref { public: Gref(): obj(NULL) {} explicit Gref(const Object &x) : obj(& x) {} const Object &get() const { if (isNull()) throw NullPointerException(); else return * obj; } bool isNull() const { if (obj == NULL) return true; return false; } private: const Object * obj; };