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 ...
随机推荐
- 如何解决浮动元素高度塌陷---CSS
解决高度塌陷问题的方法: 方法一. //给父元素添加声明 overflow:hidden; 缺点:回隐藏溢出的元素: 方法二. 在浮动的元素下添加空div标签,并给该元素添加声明: clear:bot ...
- React Native踩坑日记 —— tailwind-rn
项目背景 在项目的初始阶段,我们需要建立自己的design system,我们spike了一些方案,tailwind-rn就是其中一种,如果有用到或者即将用到tailwind-rn的,可以进来看一看, ...
- 【转】Linux 查看端口占用情况
Linux 查看端口占用情况可以使用 lsof 和 netstat 命令. lsof lsof(list open files)是一个列出当前系统打开文件的工具. lsof 查看端口占用语法格式: l ...
- 使用 elementUI 的表单进行查询,表单中只有一个文本框时,回车会自动触发表单的提交事件,导致页面的刷新。
使用elementUI的el-form组件进行查询时,当输入框仅有一项时,回车自动提交表单,浏览器会刷新页面: 原因:由于当表单只有一个文本框时,按下回车将会触发表单的提交事件, 从而导致页面刷新. ...
- BF算法(串模式匹配算法)
主串和子串 主串与子串:如果串 A(如 "shujujiegou")中包含有串 B(如 "ju"),则称串 A 为主串,串 B 为子串.主串与子串之间的关系可简 ...
- jquery获取一个元素符合条件的第一个父元素
closest jQuery 1.3新增.从元素本身开始,逐级向上级元素匹配,并返回最先匹配的元素.. closest会首先检查当前元素是否匹配,如果匹配则直接返回元素本身.如果不匹配则向上查找父元素 ...
- Java_正则表达式和文本操作
正则表达式语法 普通字符 字母.数字.汉字.下划线.以及没有特殊定义的标点符号,都是"普通字符".表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符. 简单的转义字 ...
- P4859-已经没有什么好害怕的了【容斥,dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4859 题目大意 两个长度为\(n\)的序列\(a,b\)两两匹配,求\(a_i>b_i\)的组数比\(a_ ...
- truncate表时报“唯一/主键被启用的外部关键字引用”解决办法
前言:清空表时提示"唯一/主键被启用的外部关键字引用"这一警告信息 原因:是因为主键被子表引用,所以对主键进行更改就好了 解决: 使用 alter table table_name ...
- R7000 电脑调整亮度
R7000 电脑亮度太亮,想调整亮度,fn+F5,F6 不起作用,需要调整显卡的设置