数据结构 — 浅析红黑树原理以及实现
浅析红黑树原理以及实现
bool Insert(const K& key, const V& val){//_Insert(_root, x, y);if (_root == NULL){_root = new Node(key, val);_root->_col = BLACK;}Node* cur = _root;Node* parent = cur;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key == key){return true;}}if (parent->_key > key){parent->_left = new Node(key, val);parent->_left->_parent = parent;cur = parent->_left;}else{parent->_right = new Node(key, val);parent->_right->_parent = parent;cur = parent->_right;}//目前父亲节点,插入节点,叔叔节点已经就绪.while(parent && parent->_col == RED){Node* parentparent = parent->_parent;Node* uncle = NULL;if (parentparent->_left == parent)uncle = parentparent->_right;elseuncle = parentparent->_left;if(uncle && uncle->_col == RED){parentparent->_col = RED;parent->_col = BLACK;uncle->_col = BLACK;cur = parentparent;parent = cur->_parent;}else if (uncle == NULL || uncle->_col == BLACK){if (parentparent->_left == parent){if (parent->_left == cur){RotateR(parentparent);parent->_col = BLACK;}else{RotateLR(parentparent);cur->_col = BLACK;}}else{if (parent->_right == cur){RotateL(parentparent);parent->_col = BLACK;}else{RotateRL(parentparent);cur->_col = BLACK;}}parentparent->_col = RED;if (parentparent == _root){_root = parent;}}else{assert(false);}if (_root->_col == RED){_root->_col = BLACK;}}return false;}
我们要删除del这个时候,直接删除del成本太高了,然后我们寻找一个边缘节点跟他交换,然后再删除它.所以呢,这样删除的成本是
最小的. 删除分三个情况:
1.del的左为空.
2.del的右为空.
3.del的左右都不为空.
前两种很容易思考,第三种左右都不为空的情况才需要我们的边缘替换法.所以我这里附上搜索二叉树的删除的代码. 红黑树删除的代
码暂时我还没有解决所以这里之后搜索二叉树的删除代码. 我们可以想着思考思考说不定就写完了.
代码实现:
bool Remove(const K& key){if (_root == NULL){return false;}Node* cur = _root;Node* parent = NULL;while (cur){ if (cur->key > key){parent = cur;cur = cur->_left;}else if (cur->key < key){parent = cur;cur = cur->_right;}else if (cur->key == key){break;}}Node* del = cur;if (cur->_left == NULL) //左为空{if (parent == NULL){_root = cur->_right;if (_root)_root->_parent = NULL;}else{if (parent->_left == cur)parent->_left = cur->_right;else parent->_right = cur->_right;if (cur->_right)cur->_right->_parent = parent;}}else if (cur->_right == NULL)//右为空{if (parent == NULL){_root = cur->_left;if (_root)_root->_parent = NULL;}else{if (parent->_left == cur)parent->_left = cur->_left;elseparent->_right = cur->_left;if (cur->_left)cur->_left->_parent = parent;} }else //左右都不为空{if (parent == NULL || cur == parent->_left) //如果cur在左边.{del = cur->_right;while (del->_left){del = del->_left;}del->_parent->_left = del->_right;;}else //cur在parent的右边.{del = cur->_left;while (del->_right){del = del->_right;}del->_parent->_right = del->_left;}cur->key = del->key;cur->val = del->val;}delete del;}
编写一个检验该二叉树是否为红黑树的程序:
这里首先解决一个最棘手的问题,如何判断一个路径上面的黑节点相同? 我们很容易想到,可以先遍历一条路径找到一个基准值,然
后和其他路径做比较,代码实现就是每次走到叶子结点的时候,比较该条路径的黑色节点节点个数是否和基准值相等? 如果不相等
那么返回false. 所以我们参数里面需要一个m(传递黑色节点基准值)和n(记录该条路径上面的黑色节点个数).
那么我们来瞧瞧代码实现:
bool ISRBtree(){if (_root->_col == RED){return false;}size_t n = 0;size_t m = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK){n++;}cur = cur->_left;}return _ISRBtree(_root, m, n);}bool _ISRBtree(Node* root, size_t m, size_t n){if (root == NULL){if (m == n)return true;elsereturn false;}if (root->_col == BLACK){m++;}if (root->_col == RED && root->_parent && root->_parent->_col == RED){return false;}return _ISRBtree(root->_left, m, n) && _ISRBtree(root->_right, m, n);}
演示结果:
总结
红黑树是一个非常重要的数据结构,现在生活当中的使用我们就能看的出来,可能我们并不需要它的底层构造但是我们要学习一个语
言. 最快的途径就是大师写出来的代码,手头都是资料我们要学习别人的巧妙的地方. 多看源码多多构造经典的算法,或者容器.
尝试自己编写代码,理解那个框架, 这样对我们的进步都是非常有用的.红黑树目前我就总结这么多,哪里有不足欢迎大家来指出来
,我会虚心改正.
所有代码实现:
#include<iostream>
#include<Windows.h>
#include<assert.h>
using namespace std;enum colour
{RED,BLACK
};template<class K, class V>
struct RBTreeNode
{K _key;K _val;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;colour _col;RBTreeNode(const K& key, const V& val):_key(key), _val(val), _left(NULL), _right(NULL), _parent(NULL), _col(RED){}
};template<class K, class V>
class RBTree
{typedef RBTreeNode<K, V> Node;
public:RBTree():_root(NULL){}bool Insert(const K& key, const V& val){//_Insert(_root, x, y);if (_root == NULL){_root = new Node(key, val);_root->_col = BLACK;}Node* cur = _root;Node* parent = cur;while (cur){if (cur->_key > key){parent = cur;cur = cur->_left;}else if (cur->_key < key){parent = cur;cur = cur->_right;}else if (cur->_key == key){return true;}}if (parent->_key > key){parent->_left = new Node(key, val);parent->_left->_parent = parent;cur = parent->_left;}else{parent->_right = new Node(key, val);parent->_right->_parent = parent;cur = parent->_right;}//目前父亲节点,插入节点,叔叔节点已经就绪.while(parent && parent->_col == RED){Node* parentparent = parent->_parent;Node* uncle = NULL;if (parentparent->_left == parent)uncle = parentparent->_right;elseuncle = parentparent->_left;if(uncle && uncle->_col == RED){parentparent->_col = RED;parent->_col = BLACK;uncle->_col = BLACK;cur = parentparent;parent = cur->_parent;}else if (uncle == NULL || uncle->_col == BLACK){if (parentparent->_left == parent){if (parent->_left == cur){RotateR(parentparent);parent->_col = BLACK;}else{RotateLR(parentparent);cur->_col = BLACK;}}else{if (parent->_right == cur){RotateL(parentparent);parent->_col = BLACK;}else{RotateRL(parentparent);cur->_col = BLACK;}}parentparent->_col = RED;if (parentparent == _root){_root = parent;}}else{assert(false);}if (_root->_col == RED){_root->_col = BLACK;}}return false;}bool ISRBtree(){if (_root->_col == RED){return false;}size_t n = 0;size_t m = 0;Node* cur = _root;while (cur){if (cur->_col == BLACK){n++;}cur = cur->_left;}return _ISRBtree(_root, m, n);}void print(){_print(_root);}protected:void _print(Node* root){if (root == NULL)return;_print(root->_left);cout << root->_val << " ";_print(root->_right);}bool _ISRBtree(Node* root, size_t m, size_t n){if (root == NULL){if (m == n)return true;elsereturn false;}if (root->_col == BLACK){m++;}if (root->_col == RED && root->_parent && root->_parent->_col == RED){return false;}return _ISRBtree(root->_left, m, n) && _ISRBtree(root->_right, m, n);}void RotateLR(Node*& parent){RotateL(parent->_left);RotateR(parent);}void RotateRL(Node*& parent){RotateR(parent->_right);RotateL(parent);}void RotateR(Node*& parent){Node* subL = parent->_left;Node* subLR = NULL;if (subL)subLR = subL->_right;parent->_left = subLR;if (subLR)subLR->_parent = parent;Node* ppNode = parent->_parent;subL->_right = parent;parent->_parent = subL;if (ppNode == NULL){_root = subL;_root->_parent = NULL;}else{if (ppNode->_left == parent)ppNode->_left = subL;elseppNode->_right = subL;subL->_parent = ppNode;}}void RotateL(Node*& parent){Node* subR = parent->_right;Node* subRL = NULL;if (subR)subRL = subR->_left;parent->_right = subRL;if (subRL)subRL->_parent = parent;Node* ppNode = parent->_parent;subR->_left = parent;parent->_parent = subR;if (ppNode == NULL){_root = subR;_root->_parent = NULL;}else{if (ppNode->_left == parent)ppNode->_left = subR;elseppNode->_right = subR;subR->_parent = ppNode;}}private:Node* _root;
};void Test()
{RBTree<int, int> T;//8 9 2 4 1 6 3 5T.Insert(8, 8);T.Insert(9, 9);T.Insert(2, 2);T.Insert(4, 4);T.Insert(1, 1);T.Insert(6, 6);T.Insert(3, 3);T.Insert(5, 5);cout << "该二叉树是否为红黑树??" << T.ISRBtree() << endl;T.print();system("pause");}
数据结构 — 浅析红黑树原理以及实现相关推荐
- 红黑树原理及代码实现(一)
红黑树简介 红黑树是一种自平衡的二叉查找树,它的统计性能要优于平衡二叉树,因此在很多地方都有应用,例如Java中的TreeMap,HashMap等数据结构都使用到了红黑树.红黑树对很多人来说熟悉而陌生 ...
- [Java 8 HashMap 详解系列]7.HashMap 中的红黑树原理
[Java 8 HashMap 详解系列] 文章目录 1.HashMap 的存储数据结构 2.HashMap 中 Key 的 index 是怎样计算的? 3.HashMap 的 put() 方法执行原 ...
- 红黑树 —— 原理和算法详细介绍
红黑树 -- 原理和算法详细介绍 R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为"红黑树",它一种特殊的二叉查找树.红黑树的每个节点上都有存储位 ...
- 遍历HashMap源码——红黑树原理、HashMap红黑树实现与反树型化(三)
本章将是HashMap源码的最后一章,将介绍红黑树及其实现,HashMap的remove方法与反树型化.长文预警~~ 遍历HashMap源码--红黑树原理.HashMap红黑树实现与反树型化 什么是红 ...
- HashMap红黑树原理解析
HashMap红黑树原理解析 定义: 简单来说红黑树是一种近视平衡二叉查找树,主要优点是"平衡",即左右子树高度几乎一致,以此来防止树退化为链表,通过这种方式来保障查找的时间复杂度 ...
- HashMap底层红黑树原理(超详细图解)+手写红黑树代码
在看完了小刘老师和黑马的源码视频之后,我整理了一篇HashMap的底层源码文章,学海无涯,这几天看了对红黑树的讲解,故将其整理出来 HashMap底层源码解析上 HashMap底层源码解析下 视频链接 ...
- 红黑树原理详解及golang实现
红黑树原理详解及golang实现 文章目录 红黑树原理详解及golang实现 二叉查找树 性质 红黑树 性质 operation 红黑树的插入 `情形1`:空树 `情形2`:插入节点父节为黑色, `情 ...
- 数据结构-红黑树原理分析
前言 在阅读HashMap源码的时候发现,java1.8的HashMap的链表实现增加了红黑树,当链表长度超过指定阈值8的时候回进行树化. 为了提高增删查的效率. 而红黑树又比较复杂,所以专门写一篇关 ...
- 浅析红黑树(RBTree)原理及实现
我们在上一篇博客认识到了平衡二叉树(AVLTree),了解到AVL树的性质,其实平衡二叉树最大的作用就是查找,AVL树的查找.插入和删除在平均和最坏情况下都是O(logn).AVL树的效率就是高在这个 ...
最新文章
- 树莓派c语言访问mariadb,树莓派之MariaDB
- UML图系列——UML模型图的构成
- Python脚本打包成exe文件
- 利用FRIDA攻击Android应用程序(二)
- jq添加新节点赋予class属性并获取该对象
- %=%、%%、%@%、%#%的区别
- 2023苏州大学计算机考研信息汇总
- 麒麟linux怎么安装软件,中标麒麟Linux操作系统怎么安装软件?
- migration java_如何重置migration
- ACwing 1018 最低通行费
- vs的oxc000007b错误和key valid错误
- 实战智能推荐系统(1)-- 个性化推荐系统及其基本推荐算法
- 删除office正版增值计划通知的方法
- 知道创宇 二级安全公司 骗取面试人源码,长见识了啊。
- JDK下载以及安装步骤
- OpenXml 操作Excel,Word,PPT
- vue拦截器设置请求头失败,laravel设置前端请求头跨域
- DGA(域名生成算法)/DNS tunnel
- PTA 10-53 查询部分专业的学生
- 微信 服务器 台,2W台服务器的微信过载控制系统.docx