C++实现红黑树
- 利用key_value对,快速查找,O(logn)
- socket与客户端id之间,形成映射关系(socket, id)
- 内存分配管理
- 一整块内存,不断分配小块
- 每分配一次,就加入到红黑树
- 释放的时候,在红黑树找到相应的块,然后去释放
- 利用红黑树中序遍历是顺序的特性
- 进程的调度
- 进程处于等待状态,每个进程都有等待的时间,在未来某个时刻会运行,将这些进程利用红黑树组织起来
- 在某个时刻,找到对应时刻的节点,然后中序遍历,就可以把该节点之前的节点全部运行到。
- nginx定时器
- 极少情况下,需要key是有序的,如定时器
- 左子树 < 根 < 右子树
- 中序遍历结果是顺序的
- 极端情况下,如果顺序插入,结果就成了链表
- 为了解决这个问题,引入了红黑树
- 每个节点是红色的或黑色的
- 根节点是黑色的
- 叶子节点是黑色的
- 红色节点的两个子节点必须是黑色的
- 对每个节点,该节点到其子孙节点的所有路径上的包含相同数目的黑节点(黑高相同)
- 最短路径就是全黑
- 最长路径就是黑红相间
- 采用归纳法
- 改变三个方向,六根指针
- 插入节点的时候,原先的树是满足红黑树性质的
- 插入节点的颜色是红色更容易满足红黑树的性质
- 插入的节点是红色,且其父节点也是红色的时候,需要调整
- 叔父节点是红色
- 叔父节点是黑色,且祖父节点,父节点和插入节点不是一条直线
- 叔父节点是黑色,且祖父节点,父节点和插入节点是一条直线
- 平衡二叉树:
- 内部不是color,而是一个high记录高度,如果左右子树高度相差超过1,就需要调整。
- 什么是删除节点? y-> y是z的后继节点
- 什么是轴心节点? x是y的右子树
- 如果x是红色,把x变成黑色
- 如果x是黑色,需要进行调整
- 黑色需要调整,删除黑色破坏了黑高
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define RED 1
#define BLACK 2 typedef int KEY_TYPE; typedef struct _rbtree_node {
unsigned char color;
struct _rbtree_node *right;
struct _rbtree_node *left;
struct _rbtree_node *parent;
KEY_TYPE key;
void *value;
} rbtree_node; typedef struct _rbtree {
rbtree_node *root;
rbtree_node *nil;
} rbtree; rbtree_node *rbtree_mini(rbtree *T, rbtree_node *x) {
while (x->left != T->nil) {
x = x->left;
}
return x;
} rbtree_node *rbtree_maxi(rbtree *T, rbtree_node *x) {
while (x->right != T->nil) {
x = x->right;
}
return x;
} rbtree_node *rbtree_successor(rbtree *T, rbtree_node *x) {
rbtree_node *y = x->parent; if (x->right != T->nil) {
return rbtree_mini(T, x->right);
} while ((y != T->nil) && (x == y->right)) {
x = y;
y = y->parent;
}
return y;
} void rbtree_left_rotate(rbtree *T, rbtree_node *x) { rbtree_node *y = x->right; // x --> y , y --> x, right --> left, left --> right x->right = y->left; //1 1
if (y->left != T->nil) { //1 2
y->left->parent = x;
} y->parent = x->parent; //1 3
if (x->parent == T->nil) { //1 4
T->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
} y->left = x; //1 5
x->parent = y; //1 6
} void rbtree_right_rotate(rbtree *T, rbtree_node *y) { rbtree_node *x = y->left; y->left = x->right;
if (x->right != T->nil) {
x->right->parent = y;
} x->parent = y->parent;
if (y->parent == T->nil) {
T->root = x;
} else if (y == y->parent->right) {
y->parent->right = x;
} else {
y->parent->left = x;
} x->right = y;
y->parent = x;
} void rbtree_insert_fixup(rbtree *T, rbtree_node *z) { while (z->parent->color == RED) { //z ---> RED
if (z->parent == z->parent->parent->left) {
rbtree_node *y = z->parent->parent->right;
if (y->color == RED) {
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED; z = z->parent->parent; //z --> RED
} else { if (z == z->parent->right) {
z = z->parent;
rbtree_left_rotate(T, z);
} z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_right_rotate(T, z->parent->parent);
}
}else {
rbtree_node *y = z->parent->parent->left;
if (y->color == RED) {
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED; z = z->parent->parent; //z --> RED
} else {
if (z == z->parent->left) {
z = z->parent;
rbtree_right_rotate(T, z);
} z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_left_rotate(T, z->parent->parent);
}
} } T->root->color = BLACK;
} void rbtree_insert(rbtree *T, rbtree_node *z) { rbtree_node *y = T->nil;
rbtree_node *x = T->root; while (x != T->nil) {
y = x;
if (z->key < x->key) {
x = x->left;
} else if (z->key > x->key) {
x = x->right;
} else { //Exist
return ;
}
} z->parent = y;
if (y == T->nil) {
T->root = z;
} else if (z->key < y->key) {
y->left = z;
} else {
y->right = z;
} z->left = T->nil;
z->right = T->nil;
z->color = RED; rbtree_insert_fixup(T, z);
} void rbtree_delete_fixup(rbtree *T, rbtree_node *x) { while ((x != T->root) && (x->color == BLACK)) {
if (x == x->parent->left) { rbtree_node *w= x->parent->right;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED; rbtree_left_rotate(T, x->parent);
w = x->parent->right;
} if ((w->left->color == BLACK) && (w->right->color == BLACK)) {
w->color = RED;
x = x->parent;
} else { if (w->right->color == BLACK) {
w->left->color = BLACK;
w->color = RED;
rbtree_right_rotate(T, w);
w = x->parent->right;
} w->color = x->parent->color;
x->parent->color = BLACK;
w->right->color = BLACK;
rbtree_left_rotate(T, x->parent); x = T->root;
} } else { rbtree_node *w = x->parent->left;
if (w->color == RED) {
w->color = BLACK;
x->parent->color = RED;
rbtree_right_rotate(T, x->parent);
w = x->parent->left;
} if ((w->left->color == BLACK) && (w->right->color == BLACK)) {
w->color = RED;
x = x->parent;
} else { if (w->left->color == BLACK) {
w->right->color = BLACK;
w->color = RED;
rbtree_left_rotate(T, w);
w = x->parent->left;
} w->color = x->parent->color;
x->parent->color = BLACK;
w->left->color = BLACK;
rbtree_right_rotate(T, x->parent); x = T->root;
} }
} x->color = BLACK;
} rbtree_node *rbtree_delete(rbtree *T, rbtree_node *z) { rbtree_node *y = T->nil;
rbtree_node *x = T->nil; if ((z->left == T->nil) || (z->right == T->nil)) {
y = z;
} else {
y = rbtree_successor(T, z);
} if (y->left != T->nil) {
x = y->left;
} else if (y->right != T->nil) {
x = y->right;
} x->parent = y->parent;
if (y->parent == T->nil) {
T->root = x;
} else if (y == y->parent->left) {
y->parent->left = x;
} else {
y->parent->right = x;
} if (y != z) {
z->key = y->key;
z->value = y->value;
} if (y->color == BLACK) {
rbtree_delete_fixup(T, x);
} return y;
} rbtree_node *rbtree_search(rbtree *T, KEY_TYPE key) { rbtree_node *node = T->root;
while (node != T->nil) {
if (key < node->key) {
node = node->left;
} else if (key > node->key) {
node = node->right;
} else {
return node;
}
}
return T->nil;
} void rbtree_traversal(rbtree *T, rbtree_node *node) {
if (node != T->nil) {
rbtree_traversal(T, node->left);
printf("key:%d, color:%d\n", node->key, node->color);
rbtree_traversal(T, node->right);
}
} int main() { int keyArray[20] = {24,25,13,35,23, 26,67,47,38,98, 20,19,17,49,12, 21,9,18,14,15}; rbtree *T = (rbtree *)malloc(sizeof(rbtree));
if (T == NULL) {
printf("malloc failed\n");
return -1;
} T->nil = (rbtree_node*)malloc(sizeof(rbtree_node));
T->nil->color = BLACK;
T->root = T->nil; rbtree_node *node = T->nil;
int i = 0;
for (i = 0;i < 20;i ++) {
node = (rbtree_node*)malloc(sizeof(rbtree_node));
node->key = keyArray[i];
node->value = NULL; rbtree_insert(T, node); } rbtree_traversal(T, T->root);
printf("----------------------------------------\n"); for (i = 0;i < 20;i ++) { rbtree_node *node = rbtree_search(T, keyArray[i]);
rbtree_node *cur = rbtree_delete(T, node);
free(cur); rbtree_traversal(T, T->root);
printf("----------------------------------------\n");
} }
C++实现红黑树的更多相关文章
- 红黑树——算法导论(15)
1. 什么是红黑树 (1) 简介 上一篇我们介绍了基本动态集合操作时间复杂度均为O(h)的二叉搜索树.但遗憾的是,只有当二叉搜索树高度较低时,这些集合操作才会较快:即当树的高度较高(甚至一种极 ...
- jdk源码分析红黑树——插入篇
红黑树是自平衡的排序树,自平衡的优点是减少遍历的节点,所以效率会高.如果是非平衡的二叉树,当顺序或逆序插入的时候,查找动作很可能会遍历n个节点 红黑树的规则很容易理解,但是维护这个规则难. 一.规则 ...
- 谈c++ pb_ds库(二) 红黑树大法好
厉害了,没想到翻翻pb_ds库看到这么多好东西,封装好的.现成的splay.红黑树.avl... 即使不能在考场上使用也可以用来对拍哦 声明/头文件 #include <ext/pb_ds/tr ...
- 定时器管理:nginx的红黑树和libevent的堆
libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到ac ...
- 从2-3-4树到红黑树(下) Java与C的实现
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 相关博客: 从2-3-4树到红黑树(上) 从2-3-4树到红黑树(中) 1. 实现技 ...
- 红黑树/B+树/AVL树
RB Tree 红黑树 :http://blog.csdn.net/very_2/article/details/5722682 Nginx的RBTree实现 :http://blog.csdn ...
- 论AVL树与红黑树
首先讲解一下AVL树: 例如,我们要输入这样一串数字,10,9,8,7,15,20这样一串数字来建立AVL树 1,首先输入10,得到一个根结点10 2,然后输入9, 得到10这个根结点一个左孩子结点9 ...
- DataStructure——红黑树学习笔记
1.前言 本文伪码和解释参考: http://blog.csdn.net/v_JULY_v/article/details/6105630 C实现的源码本文未贴出,请见: http://blog.cs ...
- 红黑树(Red-Black tree)
红黑树又称红-黑二叉树,它首先是一颗二叉树,它具体二叉树所有的特性.同时红黑树更是一颗自平衡的排序二叉树.我们知道一颗基本的二叉树他们都需要满足一个基本性质–即树中的任何节点的值大于它的左子节点,且小 ...
- map,hash_map, hash_table, 红黑树 的原理和使用
在刷算法题的时候总是碰到好多题,号称可以用hash table来解题.然后就蒙圈了. 1.首先,map和hash_map的区别和使用: (1)map底层用红黑树实现,hash_map底层用hash_t ...
随机推荐
- 远程桌面连接(mstsc)全攻略
打算从今天开始,写一写我经常用的,有长时间使用经验的东西,与大家分享,就从mstsc开始吧! mstsc应该是在Windows中,除了calc.cmd.notepad.mspaint,我使用率最高的系 ...
- 面试官:MySQL的幻读是怎么被解决的?
大家好,我是小林. 我之前写过一篇数据库事务的文章「 事务.事务隔离级别和MVCC」,这篇我说过什么是幻读. 在这里插入图片描述 然后前几天有位读者跟我说,我这个幻读例子不是已经被「可重复读」隔离级别 ...
- 《挑战程序设计竞赛》——DFS
DFS(深度优先搜索) 简介 深度优先搜索(DFS,Depth-First Search)是搜索的手段之一.它从某个状态开始,不断的转移状态直到无法转移.然后退回到前一步的状态,继续转移到其他状态,如 ...
- Java集合:HashMap
Hashmap是一个存储key-value的映射表. 优点: 索引数据快,查找一个数据对的时间复杂度是O(1) 增加.删除一个数据的时间复杂度是O(1) key不能重复,可以存储一个null值 存储: ...
- linux错误: locate: can not stat () `/var/lib/mlocate/mlocate.db': No such file or directory
命令 locate my.cnf 产生以上错误 此时执行 # updatedb 更新下数据库即可
- 2.docker安装及原理
一. docker的架构 1.1 docker的架构 先来看docker官网给出的docker架构图: 看官网,docker的架构描述: https://docs.docker.com/get-sta ...
- python学习笔记(九)-函数2
交换两个变量的值 a = 2 b = 1 b = 1 a = 2 #方式一: b,a = a,b #交换两个变量的值 print(a,b) #方式二: a = a + b #3 b = a - b # ...
- P5404-[CTS2019]重复【KMP,dp】
正题 题目链接:https://www.luogu.com.cn/problem/P5404 题目大意 给出一个字符串\(S\),然后求有多少个长度为\(m\)的串\(T\)满足.无限多个串\(T\) ...
- 从产业链、架构和技术三个层面,看元宇宙与RPA的发展关系
你可能还不知道,元宇宙也将带动RPA高速发展 一文读懂RPA如何赋能元宇宙,虚拟空间更需要RPA无处不在 三个层面,解读元宇宙如何利好RPA行业发展 从产业链.架构和技术三个层面,看元宇宙与RPA的发 ...
- 为什么 Dapr 如此令人兴奋
如今你构建软件,您可以从数量众多的云服务中进行选择.仅 AWS 就每个月都在不断为其200多项服务添加新服务,而其他云提供商也都在跟上. 如果您的公司想与您的竞争对手竞争,您就需要充分利用这些服务,这 ...