rbtree

一、红黑树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;
}

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

denglin12315

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值