红黑树定义:
1:根为黑,路径上黑色节点数相等。
2:不能有两个重复红
3:以null为叶子节点,且为黑色
性质:
根到叶子的长度len
2*len(min) >= len(max)
//原因:因为路径上黑色节点数相等,不能有两个重复红。
//影响:树高不会太高,查找效率不会比AVL树差多少,几乎相等
//因此RB又叫弱平衡二叉树
对比RB与AVL
查找效率几乎一样,增删时RBtree快很多(指针改动较少)
建树流程:
1:根为黑,路径上黑色节点数相等。
2:不能有两个重复红
3:以null为叶子节点,且为黑色
为了:路径上黑色节点数相等,令新插节点为红,取代null。
父为黑,结束。
父为红,则祖父必为黑,(不能有双红)。
那么可能出现四种情况:
内插/外插 * 伯父为红/伯父为黑(伯父为null时相当于黑)
插入的原则:
插入前只有2不满足。
新插节点设为红。
每次调整后,调整的子树满足RBtree规则。(只可能出现调整后节点由黑变红才需要向上遍历)。
且根到叶子节点的黑色节点数不能变。
根据ABCD子树中(从根到叶子)黑色节点的数量,
保持变化前后左右子树(从根到叶子的黑色节点数)相等。
1:外插 伯父黑
以3为要平衡的节点。
// 3是被处理过的,AB必为黑根。 平衡后new指向5。根颜色变红,向上遍历。
2:内插伯父黑
以8为要平衡的节点。
//平衡后new指向8。根颜色不变,不用向上遍历。
3:外插伯父红
以75为要平衡的节点。
//平衡后new指向80。根颜色变化,要向上遍历。
4:内插伯父红
只要改父节点与伯父节点颜色即可,同样不用向上遍历
代码思路:
类或结构体需要有的变量
Node *root;
int data;
bool red;
Node *parent = NULL;
Node *lchild = NULL;
Node *rchild = NULL;
Node* insert(Node *root, int data)
{
if(root == null)
{
root = new node(data);
root->red = true;
balance(root);
}
else
{
//根据 data与val大小选择左插右插
if() insert();else insert();
}
}
void balance(node *son)
{
//
if(son->father->red = false)
return;
if(son->father->father = null)
{
son->father->red = false; //父为根
}
int getcase(son); //8种情况 更具祖,父,子三者大小。
switch()
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
//有些指针的改变函数可以合并, 要记得传指针的地址才能真的改变指针的指向。
}
完整代码:
#include <iostream>
using namespace std;
class Node
{
public:
int data;
bool red;
Node *parent = NULL;
Node *lchild = NULL;
Node *rchild = NULL;
Node(int data, bool red = true)
{
this->data = data;
this->red = red;
}
void toggleColor()
{
this->red = !this->red;
}
};
class RBTree
{
public:
Node *root;
RBTree(int data)
{
this->root = new Node(data, false);
}
Node* insert(int data)
{
Node *current = this->root;
Node *previous = NULL;
while (current != NULL)
{
previous = current;
if (current->lchild != NULL && current->rchild != NULL &&
current->red == false && current->lchild->red == true && current->rchild->red == true)
{
this->flip(current);
this->solveCollision(current->parent, current);
}
current = data >= current->data ? current->rchild : current->lchild;
}
current = new Node(data);
if (data >= previous->data)
{
previous->rchild = current;
}
else
{
previous->lchild = current;
}
current->parent = previous;
this->solveCollision(previous, current); //调整平衡
return current;
}
protected:
void flip(Node *root)
{
if (root != this->root)
{
root->toggleColor();
}
root->lchild->toggleColor();
root->rchild->toggleColor();
}
void solveCollision(Node *parent, Node *current)
{
if (parent != NULL && current != NULL && current->red && parent->red)
{
Node *granpa = parent->parent;
Node *oldGranpa = granpa->parent;
if (granpa->lchild == parent)
{
if (parent->lchild == current)
{
this->leftOutterRotate(oldGranpa, granpa, parent, current);
}
else
{
this->leftInnerRotate(oldGranpa, granpa, parent, current);
}
}
if (granpa->rchild == parent)
{
if (parent->rchild == current)
{
this->rightOutterRotate(oldGranpa, granpa, parent, current);
}
else
{
this->rightInnerRotate(oldGranpa, granpa, parent, current);
}
}
}
}
void leftOutterRotate(Node* oldGranpa, Node* granpa, Node* parent, Node* current)
{
//toggle color
granpa->toggleColor();
parent->toggleColor();
//rotate
if (oldGranpa == NULL)
{
this->root = parent;
}
else
{
oldGranpa->lchild = parent;
}
granpa->lchild = parent->rchild;
parent->rchild = granpa;
parent->parent = oldGranpa;
granpa->parent = parent;
}
void leftInnerRotate(Node* oldGranpa, Node* granpa, Node* parent, Node* current)
{
parent->rchild = current->lchild;
current->lchild = parent;
granpa->lchild = current;
current->parent = granpa;
parent->parent = current;
this->leftOutterRotate(oldGranpa, granpa, current, parent);
}
void rightOutterRotate(Node* oldGranpa, Node* granpa, Node* parent, Node* current)
{
//toggle color
granpa->toggleColor();
parent->toggleColor();
//rotate
if (oldGranpa == NULL)
{
this->root = parent;
}
else
{
oldGranpa->rchild = parent;
}
granpa->rchild = parent->lchild;
parent->lchild = granpa;
parent->parent = oldGranpa;
granpa->parent = parent;
}
void rightInnerRotate(Node* oldGranpa, Node* granpa, Node* parent, Node* current)
{
parent->lchild = current->rchild;
current->rchild = parent;
granpa->rchild = current;
current->parent = granpa;
parent->parent = current;
this->rightOutterRotate(oldGranpa, granpa, current, parent);
}
};
int main()
{
RBTree *rbt = new RBTree(50);
rbt->insert(25);
rbt->insert(75);
rbt->insert(90);
rbt->insert(80);
}