赞
踩
○ 每个节点或是红色,或是黑色。
○ 根节点是黑色。
○ 每个叶子节点(最后的空节点,和以前的叶子节点概念不一样)是黑色的。
○ 红色节点的孩子是黑色的。 任意节点到叶子节点,经过的黑色节点数是一样的。
完全随机的数据,二分搜索树就很好用了。极端情况会退化成链表。
红黑树:添加删除查询都是2logn。翻转更少,相对来说添加比AVL要快。
红黑树:树高2logn,牺牲了一定的平衡性;但是统计性能更优(增删改查所有操作),即平均性能。
只查询的话,AVL更好;红黑树更均衡。
红黑树的各种东西太琐碎了,都是总结起来,梳理成的逻辑。看红黑树之前最好看一下2-3树。
红黑树的删除节点比添加节点还要复杂,更深入了解,再来填坑。
这里讨论的都是左倾红黑树。
插入的元素在黑节点的左侧,直接添加即可;
插入的元素在黑节点的右侧,将其左旋转,新根节点颜色继承,新孩子节点颜色变红色。
插入的元素的父节点是黑色,父节点另一个孩子是红色。直接颜色翻转即可(对应于2-3树中,3-节点插入作为临时4-节点,再分裂成为三个2-节点。然后根节点变红,继续往上融合)
插入的节点是黑节点的红节点的孩子位置,需要右旋转后反转颜色。
插入的节点是红色节点的右边。只需要先左旋转,就变成了上面的情况。
以下就是三种复杂的插入时候的情况。
即每次插入完总是下面三种情况,只需要判断是否需要左旋转、再判断是否需要右旋转、再判断是否需要颜色反转即可。
对于1.1中,插入红节点为左倾,直接不用管;插入红节点要右倾,就左旋转。即可塞入下图第二个节点的模样中。
所有的案例的逻辑为:
右孩子是红,左孩子不是红 ->左旋转
左孩子是红,左孩子的左孩子是红 ->左旋转
右孩子是红,左孩子是红 ->颜色翻转
// node x
// / \ 左旋转 / \
// T1 x ---------> node T3
// / \ / \
// T2 T3 T1 T2
// node x
// / \ 右旋转 / \
// x T2 -------> y node
// / \ / \
// y T1 T1 T2
相对于BST,插入节点加入了:
// 向以node为根的二叉搜索树中,插入节点(key, value) // 返回插入新节点后的二叉搜索树的根 Node *add(Node *node, Key key, Value value) { if (node == nullptr) { size++; return new Node(key, value); } if (key == node->key) { node->value = value; } else if (key < node->key) { node->left = add(node->left, key, value); } else { node->right = add(node->right, key, value); } node->height = 1 + std::max(getHeight(node->left), getHeight(node->right)); int balanceFactor = getBalanceFactor(node); if (balanceFactor > 1 && getBalanceFactor(node->left) >= 0) { return rightRotate(node); } if (balanceFactor < -1 && getBalanceFactor(node->right) <= 0) { return leftRotate(node); } if (balanceFactor > 1 && getBalanceFactor(node->left) < 0) { node->left = leftRotate(node->left); return rightRotate(node); } if (balanceFactor < -1 && getBalanceFactor(node->right) > 0) { node->right = rightRotate(node->right); return leftRotate(node); } return node; }
析构函数,需要用到后序遍历的思想。
即,删除当前节点,得先将其左右子树都删除掉,否则无法删除整个树。
下面代码,其实就是后序遍历的递归形式的析构函数。
// 析构函数, 释放二分搜索树的所有空间 ~BST(){ destroy( root ); } // 释放以node为根的二分搜索树的所有节点 // 采用后续遍历的递归算法 void destroy(Node* node){ if( node != NULL ){ destroy( node->left ); destroy( node->right ); delete node; count --; } }
完整代码取自bobo老师及相关同学的github,文末有路径。
template<typename Key, typename Value> class RBTree { private: static const bool RED = true; static const bool BLACK = false; struct Node { Key key; Value value; Node *left; Node *right; bool color; Node(Key key, Value value) { this->key = key; this->value = value; this->left = this->right = nullptr; color = RED; } Node(Node *node) { this->key = node->key; this->value = node->value; this->left = node->left; this->right = node->right; this->color = node->color; } }; Node *root; int size; public: RBTree() { root = nullptr; size = 0; } ~RBTree() { destroy(root); } int getSize() { return size; } int isEmpty() { return size == 0; } bool isRed(Node *node) { if (node == nullptr) { return BLACK; } return node->color; } void add(Key key, Value value) { root = add(root, key, value); root->color = BLACK; } bool contains(Key key) { return getNode(root, key) != nullptr; } Value *get(Key key) { Node *node = getNode(root, key); return node == nullptr ? nullptr : &(node->value); } void set(Key key, Value newValue) { Node *node = getNode(root, key); if (node != nullptr) { node->value = newValue; } } private: // 向以node为根的二叉搜索树中,插入节点(key, value) // 返回插入新节点后的二叉搜索树的根 Node *add(Node *node, Key key, Value value) { if (node == nullptr) { size++; return new Node(key, value); } if (key == node->key) { node->value = value; } else if (key < node->key) { node->left = add(node->left, key, value); } else { node->right = add(node->right, key, value); } if (isRed(node->right) && !isRed(node->left)) { node = leftRotate(node); } if (isRed(node->left) && isRed(node->left->left)) { node = rightRotate(node); } if (isRed(node->left) && isRed(node->right)) { flipColors(node); } return node; } // 在以node为根的二叉搜索树中查找key所对应的Node Node *getNode(Node *node, Key key) { if (node == nullptr) { return nullptr; } if (key == node->key) { return node; } else if (key < node->key) { return getNode(node->left, key); } else { return getNode(node->right, key); } } void destroy(Node *node) { if (node != nullptr) { destroy(node->left); destroy(node->right); delete node; size--; } } Node *leftRotate(Node *node) { Node *x = node->right; node->right = x->left; x->left = node; x->color = node->color; node->color = RED; return x; } Node *rightRotate(Node *node) { Node *x = node->left; node->left = x->right; x->right = node; x->color = node->color; node->color = RED; return x; } void flipColors(Node *node) { node->color = RED; node->left->color = BLACK; node->right->color = BLACK; } };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。