红黑树-RBTree

2023-11-11 23:28
文章标签 红黑树 rbtree

本文主要是介绍红黑树-RBTree,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 1. 红黑树的概念
  • 2. 红黑树的性质
  • 3. 结点的定义
  • 4. 结点的插入
  • 5. 整体代码

1. 红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的

最短路径:全黑;最长路径:一黑一红交替。

由于avl树要求严格的平衡,因此相比于红黑树来说需要更频繁的旋转来保证平衡,所以整体而言效率是比红黑树要低一点。

在这里插入图片描述

2. 红黑树的性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点必须是黑色的,保证没有任何一条路径会出现连续的红节点
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

3. 结点的定义

//枚举颜色
enum Color {RED,BLACK
};template<class K, class V>
struct RBTreeNode {RBTreeNode(const pair<const K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){ }pair<const K, V> _kv;//需要再增加一个结点颜色信息Color _col;RBTreeNode<const K, V>* _left;RBTreeNode<const K, V>* _right;//同样是需要父亲结点,后续调整旋转需要找到父亲RBTreeNode<const K, V>* _parent;
};

4. 结点的插入

往已经是满足红黑树性质的树中插入一个结点时,待插入结点的颜色一定要设置为红色,为什么?

若插入一个黑色结点,那么必然会违反性质4,若插入红色节点则不一定会违反性质3。

红黑树插入的关键在于要看叔叔结点的颜色,具体情况可分为两种:

  1. 叔叔存在且为红
    在这里插入图片描述
  2. 叔叔不存在或者叔叔存在且为黑
    在这里插入图片描述
    叔叔存在且为黑是第一种情况触发后才会出现:
    在这里插入图片描述

5. 整体代码

红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O( l o g 2 N log_2 N log2N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

#pragma once
#include <iostream>using namespace std;enum Color {RED,BLACK
};template<class K, class V>
struct RBTreeNode {RBTreeNode(const pair<const K, V>& kv):_kv(kv), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED){}pair<const K, V> _kv;enum Color _col;RBTreeNode<const K, V>* _left;RBTreeNode<const K, V>* _right;RBTreeNode<const K, V>* _parent;
};template<class K, class V>
class RBTree {typedef RBTreeNode<const K, V> Node;
public:bool insert(const pair<const K, V>& kv) {if (!_root) {_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);if (parent->_kv.first < kv.first) {parent->_right = cur;}else {parent->_left = cur;}cur->_parent = parent;//parent为红需要一直往上调整while (parent && parent->_col == RED) {Node* grandpa = parent->_parent;if (grandpa->_left == parent) {Node* uncle = grandpa->_right;//叔叔存在且为红if (uncle && uncle->_col == RED) {//把父亲和叔叔染黑//爷爷染红继续往上调整parent->_col = uncle->_col = BLACK;grandpa->_col = RED;cur = grandpa;parent = cur->_parent;}//叔叔不存在或者存在且为黑else {//单纯的一边高(直线)单旋if (cur == parent->_left) {rotateRight(grandpa);parent->_col = BLACK;cur->_col = grandpa->_col = RED;}//折线情况需要双旋else {rotateLeft(parent);rotateRight(grandpa);cur->_col = BLACK;parent->_col = grandpa->_col = RED;}break;}}//同样的逻辑else {Node* uncle = grandpa->_left;if (uncle && uncle->_col == RED) {parent->_col = uncle->_col = BLACK;grandpa->_col = RED;cur = grandpa;parent = cur->_parent;}else {if (parent->_right == cur) {rotateLeft(grandpa);grandpa->_col = cur->_col = RED;parent->_col = BLACK;}else {rotateRight(parent);rotateLeft(grandpa);parent->_col = grandpa->_col = RED;cur->_col = BLACK;}break;}		 }}_root->_col = BLACK;return true;}bool isBlance() {if (_root->_col != BLACK) {return false;}int cnt = 0;Node* cur = _root;while (cur) {cnt += cur->_col == BLACK;cur = cur->_left;}return _isBlance(_root, 0, cnt);}int getHeight() {return getHeight(_root);}private:int getHeight(Node* root) {if (!root) {return 0;}int leftH = getHeight(root->_left);int rightH = getHeight(root->_right);return max(leftH, rightH) + 1;}bool _isBlance(Node* root, int blackcnt, int t) {if (!root) {cout << blackcnt << ' ' << t << endl;return t == blackcnt;}if (root->_col == RED && root->_parent && root->_parent->_col == RED) {return false;}return _isBlance(root->_left, blackcnt + (root->_col == BLACK), t) && _isBlance(root->_right, blackcnt + (root->_col == BLACK), t);}void rotateLeft(Node* parent) {Node* cur = parent->_right;Node* curleft = cur->_left;if (curleft) {curleft->_parent = parent;}parent->_right = curleft;cur->_left = parent;Node* oldparent = parent->_parent;parent->_parent = cur;cur->_parent = oldparent;if (!oldparent) {_root = cur;}else {if (oldparent->_left == parent) {oldparent->_left = cur;}else {oldparent->_right = cur;}}}void rotateRight(Node* parent) {Node* cur = parent->_left;Node* curright = cur->_right;if (curright) {curright->_parent = parent;}parent->_left = curright;cur->_right = parent;Node* oldparent = parent->_parent;parent->_parent = cur;cur->_parent = oldparent;if (!oldparent) {_root = cur;}else {if (oldparent->_left == parent) {oldparent->_left = cur;}else {oldparent->_right = cur;}}}private:Node* _root = nullptr;
};

这篇关于红黑树-RBTree的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/393531

相关文章

红黑树的旋转

红黑树的基本性质 红黑树与普通的二叉搜索树不同,它在每个节点上附加了一个额外的属性——颜色,该颜色可以是红色或黑色。通过引入这些颜色,红黑树能够维持以下 5 个基本性质,以确保树的平衡性: 每个节点是红色或黑色。根节点是黑色。所有叶子节点(NIL 节点)是黑色。如果一个节点是红色的,那么它的两个子节点都是黑色的(即,红色节点不能有红色子节点)。从任一节点到其每个叶子节点的所有路径上都包含相同数

C++笔记19•数据结构:红黑树(RBTree)•

红黑树 1.简介:         红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或 Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路 径会比其他路径长出俩倍,因而是接近平衡的。 当搜索二叉树退化为单支树时,搜索效率极低,为了使搜索效率高,建立平衡搜索二叉树就需要"平衡树"来解决。上一篇博客介绍了AVL树,这

数据结构(13)——平衡二叉树(红黑树)

欢迎来到博主的专栏——数据结构 博主ID:代码小号 文章目录 红黑树红黑树节点之间的关系红黑树的插入uncle节点为红色uncle节点是黑色或者没有uncle节点 红黑树 平衡二叉树最出名的除了AVL树之外就是红黑树(RBTree),所谓红黑树,即拥有以下特性的平衡二叉树 (1)每个节点要么是红色,要么是黑色 (2)根节点必须是黑色 (3)红色节点的子节点必须是黑色 (

hello树先生——红黑树

红黑树 一.什么是红黑树二.红黑树的实现1.创建树节点结构2.插入功能的实现 三.提供一些常见二叉树接口四.进行平衡测试 一.什么是红黑树 红黑树是一种自平衡的二叉搜索树,具有以下特性: 节点颜色:每个节点要么是红色,要么是黑色。根节点:根节点始终是黑色。红色节点:红色节点的子节点不能是红色(即没有两个连续的红色节点)。黑色节点:从任何节点到其每个叶子节点的路径上,必须包含

数据结构-高层数据结构:映射/字典(Map)【有序字典:基于二分搜索树、基于平衡二叉树、基于红黑树、基于链表】【无序字典:基于哈希表】

Map.java package map;/*** 映射*/public interface Map<K,V> {/*** 添加元素** @param key* @param value* @return void*/void add(K key,V value);/*** 删除元素** @param key* @return V*/V remove(K key);/*** 查看是

<C++> 红黑树

目录 1. 红黑树的概念 2. 红黑树的性质 3. 红黑树节点的定义 4. 红黑树的插入操作 5. 红黑树的验证 6. 红黑树与AVL树的比较 7. 红黑树的删除         红黑树比AVL树更优一些,因为AVL要求太严格,左右高度差不超过1,而红黑树采用颜色来控制,只要求最长路径不超过最短路径的2倍,属于近似平衡 1. 红黑树的概念         红黑树,是一种二叉搜索

深入理解红黑树:在C++中实现插入、删除和查找操作

深入理解红黑树:在C++中实现插入、删除和查找操作 红黑树是一种自平衡二叉搜索树,广泛应用于各种算法和系统中。它通过颜色属性和旋转操作来保持树的平衡,从而保证插入、删除和查找操作的时间复杂度为O(log n)。本文将详细介绍如何在C++中实现一个红黑树,并提供插入、删除和查找操作的具体实现。 红黑树的基本性质 红黑树具有以下性质: 每个节点要么是红色,要么是黑色。根节点是黑色。每个叶子节点

c++ 红黑树(自平衡二叉搜索树)

目录  红黑树的概念 红黑树的由来 红黑树的性质 红黑树结点的定义 红黑树的插入 情况一:插入结点的叔叔存在,且叔叔的颜色是红色。 情况二:插入结点的叔叔存在且颜色是黑色 / 叔叔不存在, 情况A:p为g的左孩子,cur为p的左孩子 情况B:p为g的右孩子,cur为p的右孩子 情况C:p为g的左孩子,cur为p的右孩子 情况D:p为g的右孩子,cur为p的左孩子 红黑树

红黑树的模拟实现中的插入功能详细讲解,附模拟实现代码

一、红黑树的基本性质  1-1 红黑树的概念         红黑树,是一种二叉搜索树, 但不同于AVL树的点在于,红黑树维护树的平衡是通过颜色来判断,而不是通过平衡因子。红黑树的每一个节点通过增加一个存储位来表示结点的颜色,颜色分别是RED和BLACK,通过对任何一条路径上的各个结点着色方式的限制来确保其没有一条路径回避其他路径长出两倍,因而接近平衡(对于计算机来说,logN和2*logN的

红黑树概念及其性质

概念 红黑树是一种自平衡的二叉搜索树,它通过在节点上增加颜色属性并遵循一定的规则来保持树的平衡。红黑树在计算机科学中被广泛应用,特别是在需要高效查找、插入和删除操作的场景中。以下是红黑树的概念和主要性质: 红黑树的概念 结构:红黑树是一种特殊的二叉搜索树。 节点颜色:每个节点都有一个颜色属性,可以是红色或黑色。 自平衡:通过颜色变换和旋转操作来保持树的平衡。 红黑树的性质 节点