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 ...
随机推荐
- 解决git bash闪退问题 报openssl错误
问题描述:今天安装git之后发现Git Bash工具闪退. 于是试了各种办法之后,最后终于解决. 背景描述:git 下载地址:https://git-scm.com/download/win 下载成功 ...
- 理解MySQL回表
回表就是先通过数据库索引扫描出数据所在的行,再通过行主键id取出索引中未提供的数据,即基于非主键索引的查询需要多扫描一棵索引树. 因此,可以通过索引先查询出id字段,再通过主键id字段,查询行中的字段 ...
- HTML+CSS+JS设计注册页面
HTML实战--设计一个个人信息填写界面 应用的技术:HTML+CSS+JS CSS和JS是套用的模板,主要练习了表单的验证和正则表达式的使用 效果图: 代码: <!DOCTYPE html&g ...
- 【Python学习】1.数据类型
一.整数 可以使用十进制和十六进制来表示整数.比如:-1000和0x1e3f2d 二.浮点数 直接表示浮点数,比如:2.443或者1.2e5 1.2e-10等 整数和浮点数在计算机内部存储的方式是不同 ...
- PHP方法的返回值
不仅是PHP,大部分编程语言的函数或者叫方法,都可以用return来定义方法的返回值.从函数这个叫法来看,本身它就是一个计算操作,因此,计算总会有个结果,如果你在方法体中处理了结果,比如进行了持久化保 ...
- PHP中使用if的时候为什么建议将常量放在前面?
在某些框架或者高手写的代码中,我们会发现有不少人喜欢在进行条件判断的时候将常量写在前面,比如: if(1 == $a){ echo 111; } 这样做有什么好处呢?我们假设一个不小心的粗心大意,少写 ...
- Docker系列(21)- DockerFile介绍
DockerFile介绍 dockerfile是用来构建docker镜像的文件!命令参数脚本! 构建步骤 编写一个dockerfile文件 docker build构建成为一个镜像 docker ru ...
- jmeter长时间压测
如何进行24h小时的压测? 长时间压测注意事项 生成报告文件过大 https://www.cnblogs.com/SunshineKimi/p/12298668.html
- english note(6.3 to 6.8)
6.3 http://www.51voa.com/VOA_Special_English/pakistan-town-struggles-with-rise-in-hiv-infections-821 ...
- Windows下Vim插件管理器Vundle的安装以及使用简介
Vundle下载 从GitHub clone仓库 cd %USERPROFILE% git clone git@github.com:VundleVim/Vundle.vim.git %USERPRO ...