红黑树

红黑树定义:

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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值