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 ...
随机推荐
- TypeScript 中命名空间与模块的理解?区别?
一.模块 TypeScript 与ECMAScript 2015 一样,任何包含顶级 import 或者 export 的文件都被当成一个模块 相反地,如果一个文件不带有顶级的import或者expo ...
- Hadoop 2.x安装
1.关闭防火墙 systemctl stop firewalld.service #停止firewallsystemctl disable firewalld.service #禁止firewall开 ...
- 洛谷P1603——斯诺登的密码(字符串处理)
https://www.luogu.org/problem/show?pid=1603#sub 题目描述 2013年X月X日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机.但是,这件事 ...
- Elasticsearch(ES)的高级搜索(DSL搜索)(上篇)
1. 概述 之前聊了一下 Elasticsearch(ES)的基本使用,今天我们聊聊 Elasticsearch(ES)的高级搜索(DSL搜索),由于DSL搜索内容比较多,因此分为两篇文章完成. 2. ...
- Dapr实战(一) 基础概念与环境搭建
什么是Dapr Dapr 是一个可移植的.事件驱动的运行时,可运行在云平台或边缘计算中.支持多种编程语言和开发框架. 上面是官方对Dapr的介绍.有点难以理解,大白话可以理解为:Dapr是一个运行时, ...
- PHP设计模式之访问者模式
访问者,就像我们去别人家访问,或者别人来我们家看望我们一样.我们每个人都像是一个实体,而来访的人都会一一的和我们打招呼.毕竟,我们中华民族是非常讲究礼数和好客的民族.访问者是GoF23个设计模式中最复 ...
- 定要过python二级 选择第3套
1 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. . 13. 14. 15. 16. 17. (1)说明了一个问题 所谓的方向是从左到右还是从右到左 是看的是步长 步长的 ...
- 鸿蒙内核源码分析(汇编传参篇) | 如何传递复杂的参数 | 百篇博客分析OpenHarmony源码 | v23.02
百篇博客系列篇.本篇为: v23.xx 鸿蒙内核源码分析(汇编传参篇) | 如何传递复杂的参数 | 51.c.h .o 硬件架构相关篇为: v22.xx 鸿蒙内核源码分析(汇编基础篇) | CPU在哪 ...
- 【C++ Primer Plus】编程练习答案——第10章
1 // chapter10_1_account.h 2 3 #ifndef LEARN_CPP_CHAPTER10_1_ACCOUNT_H 4 #define LEARN_CPP_CHAPTER10 ...
- Python:raschii库计算任意阶数Stokes波
Stokes五阶波 最近发现一个很有用的Stokes波计算Python库,raschii官方说明,可以计算任意阶数,不同水深下的Stokes波,简单做了下测试,测试结果与脚本如下 Python 脚本 ...