文章目录

准备

博主:大大怪先森(记得关注哦!)
编程环境:vs2013
所示代码:码源


提示:写完文章后,目录可以自动生成

文章目录

  • 文章目录
  • 准备
  • 前言
  • 一、红黑树的概念
  • 二、红黑树的性质
  • 三、红黑树插入操作
    • 1.旋转图解
    • 2.代码实现
  • 四、红黑树的插入
  • 五、红黑树和AVL的比较
  • 总结

前言

本文将讲解红黑树的相关知识!!!


提示:以下是本篇文章正文内容,下面案例可供参考

一、红黑树的概念

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

二、红黑树的性质

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

三、红黑树插入操作

1.旋转图解

2.代码实现

代码如下(示例):

#define _CRT_SECURE_NO_WARNINGS 1#pragma once#include#include#includeusing namespace std;enum Colour{RED,BLACK};template<class K,class V>struct RBTreeNode{RBTreeNode<K,V>* _left;RBTreeNode<K,V>* _right;RBTreeNode<K,V>* _parent;pair<K, V> _kv;Colour _col;RBTreeNode(const pair<K,V>&kv):_left(nullptr), _right(nullptr), _parent(nullptr), _kv(kv), _col(RED){}};template<class K,class V>struct RBTree{typedef RBTreeNode<K, V> Node;public:RBTree():_root(nullptr){}bool Insert(const pair<K, V>& kv){if (_root == nullptr){_root = new Node(kv);_root->_col = BLACK;return true;}Node* parent = nullptr;Node* cur = _root;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 (parent->_kv.first < kv.first){parent->_right = cur;cur->_parent = parent;}else{parent->_left = cur;cur->_parent = parent;}//控制平衡while (parent && parent->_col == RED){Node* grandfather = parent->_parent;if (parent == grandfather->_left){Node* uncle = grandfather->_right;//1.uncle存在且为红if (uncle && uncle->_col == RED){parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else//2 + 3的情况uncle不存在//存在且为黑{if (cur == parent->_left){// g//p// c//右单旋RotateR(grandfather);parent->_col = BLACK;grandfather->_col = RED;}else{//双旋RotateL(parent);RotateR(grandfather);cur->_col = RED;grandfather->_col = BLACK;}break;}}else//parent == grandparent->_right{Node* uncle = grandfather->_left;if (uncle && uncle->_col == RED){// 变色+继续向上处理parent->_col = uncle->_col = BLACK;grandfather->_col = RED;cur = grandfather;parent = cur->_parent;}else // 2 + 3、uncle不存在/ 存在且为黑{//g// p//c//g// p//cif (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;}}void RotateR(Node* parent){Node* SubL = parent->_left;Node* SubLR = SubL->_right;parent->_left = SubLR;if (SubLR){SubLR->_parent = parent;}Node* parentParent = parent->_parent;SubL->_right = parent;parent->_parent = SubL;if (parent == _root){_root = SubL;_root->_parent = nullptr;}else{if (parentParent->_left == parent){parentParent->_left = SubL;}else{parentParent->_right = SubL;}SubL->_parent = parentParent;}}void RotateL(Node* parent){Node* subR = parent->_right;Node* subRL = subR->_left;parent->_right = subRL;if (subRL){subRL->_parent = parent;}Node* parentParent = parent->_parent;subR->_left = parent;parent->_parent = subR;if (_root == parent){_root = subR;subR->_parent = nullptr;}else{if (parentParent->_left == parent)parentParent->_left = subR;elseparentParent->_right = subR;subR->_parent = parentParent;}}void InOrder(){_InOrder(_root);}void _InOrder(Node* root){if (root == NULL)return;_InOrder(root->_left);cout << root->_kv.first << ":" << root->_kv.second << endl;_InOrder(root->_right);}bool IsBalance(){if (_root && _root->_col == RED){cout << "根节点不是黑色" << endl;return false;}// 最左路径黑色节点数量做基准值int banchmark = 0;Node* left = _root;while (left){if (left->_col == BLACK)++banchmark;left = left->_left;}int blackNum = 0;return _IsBalance(_root, banchmark, blackNum);}bool _IsBalance(Node* root, int banchmark, int blackNum){if (root == nullptr){if (banchmark != blackNum){cout << "存在路径黑色节点的数量不相等" << endl;return false;}return true;}if (root->_col == RED && root->_parent->_col == RED){cout << "出现连续红色节点" << endl;return false;}if (root->_col == BLACK){++blackNum;}return _IsBalance(root->_left, banchmark, blackNum)&& _IsBalance(root->_right, banchmark, blackNum);}int Height(){return _Height(_root);}int _Height(Node* root){if (root == NULL)return 0;int leftHeight = _Height(root->_left);int rightHeight = _Height(root->_right);return leftHeight > rightHeight " />+ 1 : rightHeight + 1;}private:Node* _root;};

四、红黑树的插入

红黑树的删除本节不做讲解,有兴趣的同学可参考:《算法导论》或者《STL源码剖析》

五、红黑树和AVL的比较

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


总结

希望本篇文章能给各位带来帮助,如有不足还请指正!!!码字不易,各位大大给个收藏点赞吧!!!

各位大大记得点赞,关注,一键三连哦!!!