概念
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或
Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路
径会比其他路径长出俩倍,因而是接近平衡的。
规则:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
插入
其实对于红黑树来说其实就是维护好一个规则,我们插入的时候每次除了第一个节点是插入节点是黑色,以后插入的新节点都是红色,插入完我们再判断是否需要去修改颜色,和旋转。修改颜色和旋转也是有公式的。
检测新节点插入后,红黑树的性质是否造到破坏
因为新节点的默认颜色是红色,因此:如果其双亲节点的颜色是黑色,没有违反红黑树任何
性质,则不需要调整;但当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连
在一起的红色节点,此时需要对红黑树分情况来讨论:
约定:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
情况一
每次当我们修改完颜色之后还需要向上循环去继续修改。
情况二
cur为红,p为红,g为黑,u不存在/u存在且为黑
情况三
其实就是需要双旋的情况
代码:
bool insert(const K&key,const V&value){if (_node == nullptr){_node = new rbtreeNode(make_pair(key, value));_node->_col = BLACK;return true;}rbtreeNode* root = _node;rbtreeNode* rootp = _node;while (root){if (key < root->_kv.first){rootp = root;root = root->_left;}else if(key>root->_kv.first){rootp = root;root = root->_right;}else{break;}}rbtreeNode* newnode = new rbtreeNode(make_pair(key,value));if (key < rootp->_kv.first){rootp->_left = newnode;}else{rootp->_right = newnode;}newnode->_parent = rootp;newnode->_col = RED;rbtreeNode* cur = newnode;while (rootp&&rootp->_col==RED){rbtreeNode* grandfather = rootp->_parent;if (grandfather->_left == rootp)// u存在且为红 -》变色再继续往上处理{rbtreeNode* uncle = grandfather->_right;if (uncle && uncle->_col == RED){uncle->_col = rootp->_col = BLACK;grandfather->_col = RED;cur = rootp;rootp = rootp->_parent;if (rootp == _node)break;}else{if (rootp->_left == cur){// g// p u//c//单旋rotateR(grandfather);rootp->_col = BLACK;grandfather->_col = RED;}else{// g// p u// c//双旋rotateL(rootp);rotateR(grandfather);grandfather->_col = RED;cur->_col = BLACK;}break;}}else{rbtreeNode* uncle = grandfather->_left;if (uncle && uncle->_col == RED){uncle->_col = rootp->_col = BLACK;grandfather->_col = RED;cur = rootp;rootp = rootp->_parent;if (rootp == _node)break;}else {if (rootp->_right == rootp){rotateL(grandfather);grandfather->_col = RED;rootp->_col = BLACK;}else{rotateR(rootp);rotateL(grandfather);grandfather->_col = RED;cur->_col = BLACK;}break;}}}_node->_col = BLACK;return true;}
红黑树的验证
这里我们也是去写一个函数去判断是否为红黑树。
bool isrbtree()
{return isrbtree(_node); //将判断函数封装起来
}bool isrbtree(rbtreeNode*root)
{if (root == nullptr){return true;}int size = 0;rbtreeNode* head = root;while (head){if (head->_col == BLACK)size++;head = head->_left; //找一个节点有多少个黑色节点,每条路径都有相同的黑色节点}if (_node->_col == RED){cout << "根为红" << endl; //如果根节点吗为红色return falsereturn false;}return iscout(root,0,size);}bool iscout(rbtreeNode*root,int count,int N)
{if (root == nullptr){if (count == N) //判断每条路径的高是否相同。return true;else{cout << count << " " << N << endl;cout << "高不同" << endl;return false;}}if (root->_col==BLACK){count++;}rbtreeNode* rootp = root->_parent;if (rootp&&rootp->_col==RED&&root->_col==RED){cout << "有在一起的红节点" << endl; //判断是否有连在一起的红节点return false;}return iscout(root->_left, count, N) && iscout(root->_right, count, N);
}