RBTree(红黑树)的递归和非递归插入

27 篇文章 0 订阅
2 篇文章 0 订阅

《算法导论》中的红⿊树

1. 每个节点或者是红⾊的,或者是⿊⾊的
2. 根节点是⿊⾊的
3. 每⼀个叶⼦节点(最后的空节点)是⿊⾊的
4. 如果⼀个节点是红⾊的,那么他的孩⼦节点都是⿊⾊的
5. 从任意⼀个节点到叶⼦节点,经过的⿊⾊节点是⼀样的
红黑树的最长路径中节点数不会超过最短路径节点个数的两倍。
最长路径:一黑一红间隔
最短路径:全黑
路径:root->NULL

非递归插入:(关键看叔叔节点判断)

#pragma once
#include<iostream>
#include<cassert>
#include<vector>

using namespace std;

enum Colour
{
	RED,
	BLACK,
};

template<class K,class V>
struct RBTreeNode {
	pair<K, V>kv;
	RBTreeNode<K,V>* parent;
	RBTreeNode<K, V>* right;
	RBTreeNode<K, V>* left;

	Colour col;

	RBTreeNode(const pair<K,V>& kv):kv(kv),parent(nullptr),right(nullptr),left(nullptr),col(RED){}

};

template<class K,class V>
class RBTree {
	typedef RBTreeNode<K, V> Node;
private:
	Node* root = nullptr;

	void RotateL(Node* parent) {
		Node* subR = parent->right;
		Node* subRL = subR->left;
		parent->right = subRL;
		if (subRL)
		{
			subRL->parent = parent;
		}
		subR->left = parent;
		Node* pparent = parent->parent;
		parent->parent = subR;
		if (parent == root)
		{
			root = subR;
			root->parent = nullptr;
		}
		else
		{
			if (parent == pparent->left)
			{
				pparent->left = subR;
			}
			else {
				pparent->right = subR;
			}
			subR->parent = pparent;
		}
	}

	void RotateR(Node* parent) {
		Node* subL = parent->left;
		Node* subLR = subL->right;

		parent->left = subLR;
		if (subLR)
		{
			subLR->parent = parent;
		}
		Node* pparent = parent->parent;
		subL->right = parent;
		parent->parent = subL;
		if (parent == root)
		{
			root = subL;
			root->parent = nullptr;
		}
		else
		{
			if (parent == pparent->left)
			{
				pparent->left = subL;
			}
			else {
				pparent->right = subL;
			}
			subL->parent = pparent;
		}
	}

	void _InOrder(Node* root)
	{
		if (root == nullptr)
			return;

		_InOrder(root->left);
		cout << root->kv.first << " ";
		_InOrder(root->right);
	}

	int _maxHeight(Node* node) {
		if (node == nullptr)
		{
			return 0;
		}
		int LH = _maxHeight(node->left);
		int RH = _maxHeight(node->right);

		return (LH > RH) ? LH + 1 : RH + 1;
	}

	int _minHeight(Node* node) {
		if (node == nullptr)
		{
			return 0;
		}
		int LH = _minHeight(node->left);
		int RH = _minHeight(node->right);

		return (LH < RH) ? LH + 1 : RH + 1;
	}

	bool _IsRBTree(Node* node, size_t k, const size_t blackCount) {
		if (node == nullptr)
		{
			if (k != blackCount)
			{
				cout << "违反性质四:每条路径的黑色节点个数相同" << endl;
				return false;
			}
			return true;
		}

		if (node->col == BLACK)
		{
			k++;
		}

		if (node->col == RED && node->parent && node->parent->col == RED)
		{
			cout << "违反性质三:不能存在连续的红色节点" << endl;
			return false;
		}

		return _IsRBTree(node->left, k, blackCount) && _IsRBTree(node->right, k, blackCount);
	}

public:

	int maxHeight() {
		return _maxHeight(root);
	}

	int minHeight() {
		return _minHeight(root);
	}

	void InOrder() {
		_InOrder(root);
	}

	bool IsRBTree() {
		Node* node = root;
		if (node == nullptr)
		{
			return true;
		}

		if (node->col != BLACK)
		{
			cout << "根的节点不为黑色" << endl;
			return false;
		}

		size_t blackCount = 0;
		Node* cur = node;
		while (cur)
		{
			if (cur->col == BLACK)
				blackCount++;
			cur = cur->left;
		}

		size_t k = 0;

		return _IsRBTree(root, k, blackCount);
	}

	bool Insert(const pair<K, V>& kv) {
		if (root == nullptr)
		{
			root = new Node(kv);
			root->col = BLACK;
			return true;
		}
		Node* cur = root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->kv.first < kv.first) {
				parent = cur;
				cur = cur->right;
			}
			else if (cur->kv.first > kv.first)
			{
				parent = cur;
				cur = cur->left;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		cur->col = RED;
		if (kv.first < parent->kv.first)
		{
			parent->left = cur;
		}
		else {
			parent->right = cur;
		}
		cur->parent = parent;
		while (parent && parent->col == RED)
		{
			Node* grandfather = parent->parent;
			if (parent == grandfather->left)
			{
				Node* uncle = grandfather->right;
				if (uncle && uncle->col == RED)
				{
					parent->col = uncle->col = BLACK;
					grandfather->col = RED;
					cur = grandfather;
					parent = cur->parent;
				}
				else //uncle不存在或存在且为黑色
				{
					if (cur == parent->left)
					{
						RotateR(grandfather);
						parent->col = BLACK;
						grandfather->col = RED;
					}
					else
					{
						RotateL(parent);
						RotateR(grandfather);
						cur->col = BLACK;
						grandfather->col = RED;
					}
					break;
				}
			}
			else {
				Node* uncle = grandfather->left;
				if (uncle && uncle->col == RED)
				{
					parent->col = uncle->col = BLACK;
					grandfather->col = RED;
					cur = grandfather;
					parent = cur->parent;
				}
				else
				{
					if (cur == parent->right)
					{
						RotateL(grandfather);
						parent->col = BLACK;
						grandfather->col = RED;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						cur->col = BLACK;
						grandfather->col = RED;
					}
					break;
				}
			}
		}
		root->col = BLACK;
		return true;
	}
};

void testRBTree1() {
	int a[] = { 30, 29, 28, 27, 26, 25, 24, 11, 8, 7, 6, 5, 4, 3, 2, 1 };
	RBTree<int, int> t;
	for (auto e : a)
	{
		t.Insert(make_pair(e, e));
	}
	t.InOrder();
}

void testRBTree2() {
	const int N = 1000;
	vector<int>v;
	srand(time(0));
	for (size_t i = 0; i < N; i++)
	{
		//v.push_back(i);
		v.push_back(rand());
	}
	RBTree<int, int>rbTree;
	for (auto e : v) {
		rbTree.Insert(make_pair(e, e));
	}

	cout << "是否平衡?" << rbTree.IsRBTree() << endl;
	cout << "最小高度 = " << rbTree.minHeight() << endl;
	cout << "最大高度 = " << rbTree.maxHeight() << endl;

	rbTree.InOrder();

}

递归插入:(主要和2-3树的插入操作相似,如更好的理解红黑树和B树,请先了解2-3树)

//
// Created by hpf on 18-7-16.
//

#ifndef RED_BLACK_TREE_RBTREE_H
#define RED_BLACK_TREE_RBTREE_H

#include <iostream>
#include <vector>

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;
    }
};

#endif //RED_BLACK_TREE_RBTREE_H

红黑树的性能总结

对于完全随机的数据,普通的⼆分搜索树很好⽤!
缺点:极端情况退化成链表(或者⾼度不平衡)
对于查询较多的使⽤情况, AVL 树很好⽤!
红⿊树牺牲了平衡性( 2logn 的⾼度)
统计性能更优 (综合增删改查所有的操作)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值