一、红黑树6条规则
1.每个节点非黑即红
2.根节点是黑色
3.新插入的节点是红色
4.从根到叶节点的所有路径经历的黑节点个数相等
5.从根到叶节点不存在两个连续红色节点的路径
6.空节点(sentinel节点)是黑色的——很多情况下aunt节点就是空节点
二、插入新节点导致红黑树规则冲突后的reblance操作(受影响的节点parent/grand parent/aunt)
1.reblance操作分类
1)rotate(rotate对象是问题节点的grand parent) —— black aunt
2) colorfilp —— red aunt
从问题child节点出发,范围只是在当前问题节点(多为插入节点)的parent/grand parent/aunt/self节点
2.after rotation:
3.after colorfilp
三、举个例子
四、代码实例
rbtree_amd.h
/*
* Copyright © 2018 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including
* the next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef _RBTREE_AMD_H_
#define _RBTREE_AMD_H_
typedef struct rbtree_key_s rbtree_key_t;
struct rbtree_key_s {
#define ADDR_BIT 0
#define SIZE_BIT 1
unsigned long addr;
unsigned long size;
};
#define BIT(x) (1<<(x))
#define LKP_ALL (BIT(ADDR_BIT) | BIT(SIZE_BIT))
#define LKP_ADDR (BIT(ADDR_BIT))
#define LKP_ADDR_SIZE (BIT(ADDR_BIT) | BIT(SIZE_BIT))
static inline rbtree_key_t
rbtree_key(unsigned long addr, unsigned long size)
{
return (rbtree_key_t){addr, size};
}
/*
* compare addr, size one by one
*/
static inline int
rbtree_key_compare(unsigned int type, rbtree_key_t *key1, rbtree_key_t *key2)
{
if ((type & 1 << ADDR_BIT) && (key1->addr != key2->addr))
return key1->addr > key2->addr ? 1 : -1;
if ((type & 1 << SIZE_BIT) && (key1->size != key2->size))
return key1->size > key2->size ? 1 : -1;
return 0;
}
#endif /*_RBTREE_AMD_H_*/
/*inlcude this file again with RBTREE_HELPER defined*/
#ifndef RBTREE_HELPER
#define RBTREE_HELPER
#else
#ifndef _RBTREE_AMD_H_HELPER_
#define _RBTREE_AMD_H_HELPER_
static inline rbtree_node_t *
rbtree_max(rbtree_node_t *node, rbtree_node_t *sentinel)
{
while (node->right != sentinel)
node = node->right;
return node;
}
#define LEFT 0
#define RIGHT 1
#define MID 2
static inline rbtree_node_t *
rbtree_min_max(rbtree_t *tree, int lr)
{
rbtree_node_t *sentinel = &tree->sentinel;
rbtree_node_t *node = tree->root;
if (node == sentinel)
return NULL;
if (lr == LEFT)
node = rbtree_min(node, sentinel);
else if (lr == RIGHT)
node = rbtree_max(node, sentinel);
return node;
}
static inline rbtree_node_t *
rbtree_node_any(rbtree_t *tree, int lmr)
{
rbtree_node_t *sentinel = &tree->sentinel;
rbtree_node_t *node = tree->root;
if (node == sentinel)
return NULL;
if (lmr == MID)
return node;
return rbtree_min_max(tree, lmr);
}
static inline rbtree_node_t *
rbtree_lookup_nearest(rbtree_t *rbtree, rbtree_key_t *key,
unsigned int type, int lr)
{
int rc;
rbtree_node_t *node, *sentinel, *n = NULL;
node = rbtree->root;
sentinel = &rbtree->sentinel;
while (node != sentinel) {
rc = rbtree_key_compare(type, key, &node->key);
if (rc < 0) {
if (lr == RIGHT)
n = node;
node = node->left;
continue;
}
if (rc > 0) {
if (lr == LEFT)
n = node;
node = node->right;
continue;
}
return node;
}
return n;
}
static inline rbtree_node_t *
rbtree_lookup(rbtree_t *rbtree, rbtree_key_t *key,
unsigned int type)
{
return rbtree_lookup_nearest(rbtree, key, type, -1);
}
#endif /*_RBTREE_AMD_H_HELPER_*/
#endif /*RBTREE_HELPER*/
rbtree.h
/*
* Copyright (C) 2002-2018 Igor Sysoev
* Copyright (C) 2011-2018 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _RBTREE_H_
#define _RBTREE_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <errno.h>
#include "rbtree_amd.h"
typedef struct rbtree_node_s rbtree_node_t;
struct rbtree_node_s {
rbtree_key_t key;
rbtree_node_t *left;
rbtree_node_t *right;
rbtree_node_t *parent;
unsigned char color;
unsigned char data;
};
typedef struct rbtree_s rbtree_t;
struct rbtree_s {
rbtree_node_t *root;
rbtree_node_t sentinel;
};
#define rbtree_init(tree) \
rbtree_sentinel_init(&(tree)->sentinel); \
(tree)->root = &(tree)->sentinel;
void rbtree_insert(rbtree_t *tree, rbtree_node_t *node);
void rbtree_delete(rbtree_t *tree, rbtree_node_t *node);
rbtree_node_t *rbtree_next(rbtree_t *tree,
rbtree_node_t *node);
#define rbt_red(node) ((node)->color = 1)
#define rbt_black(node) ((node)->color = 0)
#define rbt_is_red(node) ((node)->color)
#define rbt_is_black(node) (!rbt_is_red(node))
#define rbt_copy_color(n1, n2) (n1->color = n2->color)
/* a sentinel must be black */
#define rbtree_sentinel_init(node) rbt_black(node)
static inline rbtree_node_t *
rbtree_min(rbtree_node_t *node, rbtree_node_t *sentinel)
{
while (node->left != sentinel) {
node = node->left;
}
return node;
}
#include "rbtree_amd.h"
#endif
rbtree.c
/*
* Copyright (C) 2002-2018 Igor Sysoev
* Copyright (C) 2011-2018 Nginx, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "rbtree.h"
static inline void rbtree_left_rotate(rbtree_node_t **root,
rbtree_node_t *sentinel, rbtree_node_t *node);
static inline void rbtree_right_rotate(rbtree_node_t **root,
rbtree_node_t *sentinel, rbtree_node_t *node);
static void
rbtree_insert_value(rbtree_node_t *temp, rbtree_node_t *node,
rbtree_node_t *sentinel)
{
rbtree_node_t **p;
for ( ;; ) {
p = rbtree_key_compare(LKP_ALL, &node->key, &temp->key) < 0 ?
&temp->left : &temp->right;
if (*p == sentinel) {
break;
}
temp = *p;
}
*p = node;
node->parent = temp;
node->left = sentinel;
node->right = sentinel;
rbt_red(node);
}
void
rbtree_insert(rbtree_t *tree, rbtree_node_t *node)
{
rbtree_node_t **root, *temp, *sentinel;
/* a binary tree insert */
root = &tree->root; //找到树的根节点
sentinel = &tree->sentinel; //找到树的哨兵
//空树插入第一个节点
if (*root == sentinel) {
node->parent = NULL;
node->left = sentinel;
node->right = sentinel;
rbt_black(node);
*root = node;
return;
}
//非空树插入节点
rbtree_insert_value(*root, node, sentinel);
/* re-balance tree */
while (node != *root && rbt_is_red(node->parent)) {
if (node->parent == node->parent->parent->left) {
temp = node->parent->parent->right;
if (rbt_is_red(temp)) {
rbt_black(node->parent);
rbt_black(temp);
rbt_red(node->parent->parent);
node = node->parent->parent;
} else {
if (node == node->parent->right) {
node = node->parent;
rbtree_left_rotate(root, sentinel, node);
}
rbt_black(node->parent);
rbt_red(node->parent->parent);
rbtree_right_rotate(root, sentinel, node->parent->parent);
}
} else {
temp = node->parent->parent->left;
if (rbt_is_red(temp)) {
rbt_black(node->parent);
rbt_black(temp);
rbt_red(node->parent->parent);
node = node->parent->parent;
} else {
if (node == node->parent->left) {
node = node->parent;
rbtree_right_rotate(root, sentinel, node);
}
rbt_black(node->parent);
rbt_red(node->parent->parent);
rbtree_left_rotate(root, sentinel, node->parent->parent);
}
}
}
rbt_black(*root);
}
void
rbtree_delete(rbtree_t *tree, rbtree_node_t *node)
{
unsigned int red;
rbtree_node_t **root, *sentinel, *subst, *temp, *w;
/* a binary tree delete */
root = &tree->root;
sentinel = &tree->sentinel;
if (node->left == sentinel) {
temp = node->right;
subst = node;
} else if (node->right == sentinel) {
temp = node->left;
subst = node;
} else {
subst = rbtree_min(node->right, sentinel);
if (subst->left != sentinel) {
temp = subst->left;
} else {
temp = subst->right;
}
}
if (subst == *root) {
*root = temp;
rbt_black(temp);
return;
}
red = rbt_is_red(subst);
if (subst == subst->parent->left) {
subst->parent->left = temp;
} else {
subst->parent->right = temp;
}
if (subst == node) {
temp->parent = subst->parent;
} else {
if (subst->parent == node) {
temp->parent = subst;
} else {
temp->parent = subst->parent;
}
subst->left = node->left;
subst->right = node->right;
subst->parent = node->parent;
rbt_copy_color(subst, node);
if (node == *root) {
*root = subst;
} else {
if (node == node->parent->left) {
node->parent->left = subst;
} else {
node->parent->right = subst;
}
}
if (subst->left != sentinel) {
subst->left->parent = subst;
}
if (subst->right != sentinel) {
subst->right->parent = subst;
}
}
if (red) {
return;
}
/* a delete fixup */
while (temp != *root && rbt_is_black(temp)) {
if (temp == temp->parent->left) {
w = temp->parent->right;
if (rbt_is_red(w)) {
rbt_black(w);
rbt_red(temp->parent);
rbtree_left_rotate(root, sentinel, temp->parent);
w = temp->parent->right;
}
if (rbt_is_black(w->left) && rbt_is_black(w->right)) {
rbt_red(w);
temp = temp->parent;
} else {
if (rbt_is_black(w->right)) {
rbt_black(w->left);
rbt_red(w);
rbtree_right_rotate(root, sentinel, w);
w = temp->parent->right;
}
rbt_copy_color(w, temp->parent);
rbt_black(temp->parent);
rbt_black(w->right);
rbtree_left_rotate(root, sentinel, temp->parent);
temp = *root;
}
} else {
w = temp->parent->left;
if (rbt_is_red(w)) {
rbt_black(w);
rbt_red(temp->parent);
rbtree_right_rotate(root, sentinel, temp->parent);
w = temp->parent->left;
}
if (rbt_is_black(w->left) && rbt_is_black(w->right)) {
rbt_red(w);
temp = temp->parent;
} else {
if (rbt_is_black(w->left)) {
rbt_black(w->right);
rbt_red(w);
rbtree_left_rotate(root, sentinel, w);
w = temp->parent->left;
}
rbt_copy_color(w, temp->parent);
rbt_black(temp->parent);
rbt_black(w->left);
rbtree_right_rotate(root, sentinel, temp->parent);
temp = *root;
}
}
}
rbt_black(temp);
}
static inline void
rbtree_left_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
rbtree_node_t *node)
{
rbtree_node_t *temp;
temp = node->right;
node->right = temp->left;
if (temp->left != sentinel) {
temp->left->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
} else if (node == node->parent->left) {
node->parent->left = temp;
} else {
node->parent->right = temp;
}
temp->left = node;
node->parent = temp;
}
static inline void
rbtree_right_rotate(rbtree_node_t **root, rbtree_node_t *sentinel,
rbtree_node_t *node)
{
rbtree_node_t *temp;
temp = node->left;
node->left = temp->right;
if (temp->right != sentinel) {
temp->right->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
} else if (node == node->parent->right) {
node->parent->right = temp;
} else {
node->parent->left = temp;
}
temp->right = node;
node->parent = temp;
}
rbtree_node_t *
rbtree_next(rbtree_t *tree, rbtree_node_t *node)
{
rbtree_node_t *root, *sentinel, *parent;
sentinel = &tree->sentinel;
if (node->right != sentinel) {
return rbtree_min(node->right, sentinel);
}
root = tree->root;
for ( ;; ) {
parent = node->parent;
if (node == root) {
return NULL;
}
if (node == parent->left) {
return parent;
}
node = parent;
}
}
main.c
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include "rbtree.h"
typedef struct memory_node {
uint64_t start;
uint64_t size;
rbtree_node_t rbtree_node;
} memory_node_t;
#define container_of(ptr, type, member) ({ \
char *__mptr = (void *)(ptr); \
((type *)(__mptr - offsetof(type, member))); })
static memory_node_t *memory_node_find_by_address(rbtree_t *tree, const void *address,
uint64_t size)
{
memory_node_t *cur = NULL;
rbtree_key_t key = rbtree_key((unsigned long)address, size);
void *start;
uint64_t s;
/* rbtree_lookup_nearest(,,,RIGHT) will return a node with
* its size >= key.size and its address >= key.address
* if there are two nodes with format(address, size),
* (0x100, 16) and (0x110, 8). the key is (0x100, 0),
* then node (0x100, 16) will be returned.
*/
rbtree_node_t *n = rbtree_lookup_nearest(tree, &key, LKP_ALL, RIGHT);
if (n) {
cur = container_of(n, memory_node_t, rbtree_node);
start = cur->start;
s = cur->size;
if (start != address)
return NULL;
if (size)
return size == s ? cur : NULL;
/* size is 0, make sure there is only one node whose address == key.address*/
key = rbtree_key((unsigned long)address, (unsigned long)-1);
rbtree_node_t *rn = rbtree_lookup_nearest(tree, &key, LKP_ALL, LEFT);
if (rn != n)
return NULL;
}
return cur; /* NULL if not found */
}
int main(int argc, char **argv)
{
rbtree_t tree;
memory_node_t *node;
memory_node_t *node2;
memory_node_t *get_node;
memory_node_t *get_node2;
uint64_t addr;
uint64_t size;
//树初始化
rbtree_init(&tree);
//节点和节点key创建
addr = 0x40000000;
size = 0x1000;
node = (memory_node_t *)malloc(sizeof(memory_node_t));
node->start = addr;
node->size = size;
node->rbtree_node.key = rbtree_key(addr, size);
//将node插入到tree中
rbtree_insert(&tree, &(node->rbtree_node));
//节点和节点key创建
addr = 0x80000000;
size = 0x2000;
node2 = (memory_node_t *)malloc(sizeof(memory_node_t));
node2->start = addr;
node2->size = size;
node2->rbtree_node.key = rbtree_key(addr, size);
//将node插入到tree中
rbtree_insert(&tree, &(node2->rbtree_node));
get_node = memory_node_find_by_address(&tree, 0x40000000, 0x1000);
printf("node1,start:%lx,size:%lx\n", get_node->start, get_node->size);
get_node2 = memory_node_find_by_address(&tree, 0x80000000, 0x2000);
printf("node2,start:%lx,size:%lx\n", get_node2->start, get_node2->size);
return 0;
}