红黑树实现

直接上代码

/*
 * bst.h
 *
 *  Created on: Jun 20, 2014
 *      Author: buyuanyuan
 */

#ifndef BST_H_
#define BST_H_

#include <stdint.h>
#include <stdbool.h>

typedef enum Color {
	RED = 0,
    BLACK = 1
} Color;

typedef struct Node {
	char *key;
	Color color;
	uint64_t value;
	struct Node *left, *right, *parent;
} RBT;

RBT *rbt_insert(RBT *root, char *key, uint64_t value);

uint64_t rbt_search(RBT *root, char *key);

RBT* rbt_delete(RBT *root, char *key);

uint8_t rbt_destory(RBT *root);

#endif /* BST_H_ */
/*
 * RBT.c
 *
 *  Created on: Jun 20, 2014
 *      Author: buyuanyuan
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "rbt.h"

static RBT *rotate_left(RBT *node, RBT *root)
{
	RBT* right = node->right;
	if((node->right = right->left)) {
		right->left->parent = node;
	}
	right->left = node;
	if((right->parent = node->parent)) {
		if(node == node->parent->right) {
			node->parent->right = right;
		} else {
			node->parent->left = right;
		}
	} else {
		root = right;
	}
	node->parent = right;
	return root;
}

static RBT *rotate_right(RBT *node, RBT *root)
{
	RBT* left = node->left;
	if((node->left = left->right)) {
		left->right->parent = node;
	}
	left->right = node;
	if((left->parent = node->parent)) {
		if(node == node->parent->right) {
			node->parent->right = left;
		} else {
			node->parent->left = left;
		}
	} else {
		root = left;
	}
	node->parent = left;
	return root;
}

static RBT *insert_case(RBT *node, RBT *root)
{
	RBT *parent, *gparent, *uncle, *tmp;
	while ((parent = node->parent) && parent->color == RED){
		gparent = parent->parent;
		if (parent == gparent->left){
			uncle = gparent->right;
			if (uncle && uncle->color == RED){
				uncle->color = BLACK;
				parent->color = BLACK;
				gparent->color = RED;
				node = gparent;
			}else{
				if (parent->right == node){
					root = rotate_left(parent, root);
					tmp = parent;
					parent = node;
					node = tmp;
				}
				parent->color = BLACK;
				gparent->color = RED;
				root = rotate_right(gparent, root);
			}
		}else{
			uncle = gparent->left;
			if (uncle && uncle->color == RED){
				uncle->color = BLACK;
				parent->color = BLACK;
				gparent->color = RED;
				node = gparent;
			}else{
				if (parent->left == node){
					root = rotate_right(parent, root);
					tmp = parent;
					parent = node;
					node = tmp;
				}
				parent->color = BLACK;
				gparent->color = RED;
				root = rotate_left(gparent, root);
			}
		}
	}
	root->color = BLACK;
	return root;
}
static RBT *delete_case(RBT *node, RBT *parent, RBT *root)
{
	RBT *other, *o_left, *o_right;
	while((!node || node->color == BLACK) && node != root) {
		if(parent->left == node) {
			other = parent->right;
			if(other->color == RED) {
				other->color = BLACK;
				parent->color = RED;
				root = rotate_left(parent, root);
				other = parent->right;
			}
			if((!other->left || other->left->color == BLACK) &&
					(!other->right || other->right->color == BLACK)) {
				other->color = RED;
				node = parent;
				parent = node->parent;
			} else {
				if(!other->right || other->right->color == BLACK) {
					if((o_left = other->left)) {
						o_left->color = BLACK;
					}
					other->color = RED;
					root = rotate_right(other, root);
					other = parent->right;
				}
				other->color = parent->color;
				parent->color = BLACK;
				if(other->right) {
					other->right->color = BLACK;
				}
				root = rotate_left(parent, root);
				node = root;
				break;
			}
		} else {
			other = parent->left;
			if(other->color == RED) {
				other->color = BLACK;
				parent->color = RED;
				root = rotate_right(parent, root);
				other = parent->left;
			}
			if((!other->left || other->left->color == BLACK) &&
					(!other->right || other->right->color == BLACK)) {
				other->color = RED;
				node = parent;
				parent = node->parent;
			} else {
				if(!other->left || other->left->color == BLACK) {
					if((o_right = other->right)) {
						o_right->color = BLACK;
					}
					other->color = RED;
					root = rotate_left(other, root);
					other = parent->left;
				}
				other->color = parent->color;
				parent->color = BLACK;
				if(other->left) {
					other->left->color = BLACK;
				}
				root = rotate_right(parent, root);
				node = root;
				break;
			}
		}
	}
	if(node) {
		node->color = BLACK;
	}
	return root;
}

static RBT *search_data(char *key, RBT *root, RBT **save)
{
	if(root == NULL) {
		return NULL;
	}
	RBT *node = root, *parent = NULL;
	int64_t ret;
	while (node) {
		parent = node;
		ret = strcmp(node->key, key);
		if (0 < ret) {
			node = node->left;
		} else if (0 > ret) {
			node = node->right;
		} else {
			return node;
		}
	}
	if (save) {
		*save = parent;
	}
	return NULL;
}

static uint8_t destory_all(RBT *root)
{
	while(root != NULL) {
		root = delete(root, root->key);
	}
	if(root == NULL) {
		return 1;
	} else {
		return 0;
	}
}

RBT* rbt_insert(RBT *root, char *key, uint64_t data)
{
	RBT *parent = NULL;
	RBT *node = NULL;
	if ((node = search_data(key, root, &parent))) {
		return root;
	}
	node = (RBT *)malloc(sizeof(RBT));
	if(!node) {
		printf("malloc error!");
		exit(-1);
	}
	node->key = (char *)malloc(strlen(key) + 1);
	memset(node->key, strlen(key)+1, 0);
	strcpy(node->key, key);
	node->value = data;
	node->parent = parent;
	node->left = node->right = NULL;
	node->color = RED;
	if (parent) {
		if(strcmp(parent->key, key)> 0) {
			parent->left = node;
		} else {
			parent->right = node;
		}
	} else {
		root = node;
	}
	return insert_case(node, root);
}

uint64_t rbt_search(RBT *root, char *key)
{
	RBT *node = search_data(key, root, NULL);
	if(node) {
		return node->value;
	} else {
		return -1;
	}
}

RBT *rbt_delete(RBT *root, char *key)
{
	RBT *child, *parent, *old, *left, *node;
	Color color;
	if (!(node = search_data(key, root, NULL))) {
		printf("key %s is not exist!\n", key);
		return root;
	}
	old = node;
	if (node->left && node->right) {
		node = node->right;
		while ((left = node->left) != NULL) {
			node = left;
		}
		child = node->right;
		parent = node->parent;
		color = node->color;
		if (child) {
			child->parent = parent;
		}
		if (parent) {
			if (parent->left == node) {
				parent->left = child;
			} else {
				parent->right = child;
			}
		} else {
			root = child;
		}
		if (node->parent == old) {
			parent = node;
		}
		node->parent = old->parent;
		node->color = old->color;
		node->right = old->right;
		node->left = old->left;
		if (old->parent) {
			if (old->parent->left == old) {
				old->parent->left = node;
			} else {
				old->parent->right = node;
			}
		} else {
			root = node;
		}
		old->left->parent = node;
		if(old->right) {
			old->right->parent = node;
		}
	} else {
		if (!node->left) {
			child = node->right;
		}
		else if (!node->right) {
			child = node->left;
		}
		parent = node->parent;
		color = node->color;
		if (child) {
			child->parent = parent;
		}
		if (parent) {
			if (parent->left == node) {
				parent->left = child;
			} else {
				parent->right = child;
			}
		} else {
			root = child;
		}
	}
	free(old->key);
	free(old);
	if (color == BLACK) {
		root = delete_case(child, parent, root);
	}
	return root;
}

uint8_t rbt_destory(RBT *root)
{
	return destory_all(root);
}

红黑树实现

时间: 2024-08-02 05:52:02

红黑树实现的相关文章

B树、B+树、红黑树、AVL树比较

B树是为了提高磁盘或外部存储设备查找效率而产生的一种多路平衡查找树. B+树为B树的变形结构,用于大多数数据库或文件系统的存储而设计. B树相对于红黑树的区别 在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况.为什么会出现这样的情况,我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写.磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读

红黑树之删除节点

红黑树之删除节点 上一篇文章中讲了如何向红黑树中添加节点,也顺便创建了一棵红黑树.今天写写怎样从红黑树中删除节点. 相比于添加节点,删除节点要复杂的多.不过我们慢慢梳理,还是能够弄明白的. 回顾一下红黑树的性质 红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色.在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求: 节点是红色或黑色. 根节点是黑色. 每个叶节点(这里的叶节点是指NULL节点,在<算法导论>中这个节点叫哨兵节点,除了颜色属性外,其他属性值都为任

数据结构与算法-红黑树

前言 红黑树是工程中最常用到的一种自平衡二叉排序树,其和AVL树类似,都是在进行插入.删除时通过一定的调整操作来维持相对稳定的树高,从而获得较好的查询性能. 性质 1. 节点是红色或黑色. 2. 根节点是黑色. 3 每个叶节点(null节点)是黑色的. 4 每个红色节点的两个子节点都是黑色.(从每个叶子到根的所有路径上不能有两个连续的红色节点) 5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点. 维护红黑树形状(树高)的,主要就是4.5两条性质,性质4决定了最长的路径莫过于红黑间隔

数据结构学习笔记-排序/队/栈/链/堆/查找树/红黑树

排序: 插入排序:每次从剩余数据中选取一个最小的,插入已经排序完成的序列中 合并排序:将数据分成左右两组分别排序,然后合并,对每组数据的排序递归处理. 冒泡排序:重复交换两个相邻元素,从a[1]开始向a[0]方向冒泡,然后a[2]...当a[i]无法继续往前挤的时候说明前面的更小了,而且越往前越小(挤得越往前) 堆排序:构造最大堆,每次取走根结点(自然是最大的),再调用MAX-HEAPIFY算法(见后文的堆)恢复最大堆的性质,重复取走根结点 快速排序(对A[r]-A[n]进行排序): 1.从序列

红黑树与AVL(平衡二叉树)的区别

关于红黑树和AVL树,来自网络: 1 好处 及 用途 红黑树 并不追求"完全平衡 "--它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能. 红黑树能够以 O(log2  n)  的时间复杂度进行搜索.插入.删除操作.此外,由于它的设计,任何不平衡都会在三次旋转之内解决.当然,还有一些更好的,但实现起来更复杂的数据结构 能够做到一步旋转之内达到平衡,但红黑树能够给我们一个比较"便宜"的解决方案.红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高

数据结构-红黑树

转自:http://dongxicheng.org/structure/red-black-tree/ 1. 简介 红黑树是一种自平衡二叉查找树.它的统计性能要好于平衡二叉树(AVL树),因此,红黑树在很多地方都有应用.在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持).它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它

红黑树

弄了很久,学习过程中觉得很难,但学完了,其实感觉也就那样,就是情况多了些. 首先是插入,插入的时候其实也就3种情况,因为只有当插入的节点的父亲是红色的时候,此时红黑树的性质遭到破坏,需要旋转,再分1.叔父节点为红,此时只要改变颜色,但祖父节点颜色的改变可能会破坏红黑树的性质,所以要node = grandparent,继续向上,叔父为黑,这时需要旋转,所以得判断,自身的位置,也就是自己和父亲分别是左孩子还是右孩子,2.如果自身是右,父亲是左,的先把自己也旋转到左,再和自己是左,父亲也是左的情况一

定时器管理:nginx的红黑树和libevent的堆

libevent 发生超时后, while循环一次从堆顶del timer——直到最新调整的最小堆顶不是超时事件为止,(实际是del event),但是会稍后把这个timeout的 event放到active 任务list里, 等待处理,event标记为timeout,等处理actvie队列时再由应用层callback函数决定怎么处理标记为timeout的事件. nginx处理超时时,直接删除红黑树中( event结构体里的 )rb node成员,同时调用应用层早已通过add timer注册好的

数据结构——红黑树

红黑树是二叉排序树的改进, 红黑树有几个特点: 1:节点只有2中颜色,红色和黑色. 2:根节点一定是黑色节点. 3:红色节点的子节点一定是黑色节点. 4:黑色高度(根节点到每个叶子节点的路径长度包含相同的黑色节点)相等. 规定的插入的节点一定是红色节点, 红黑树的插入节点后需要调整的规则,插入节点需要调整的情况有3种: 情况1:插入的节点的父节点和叔叔节点都为红色: 以上情况节点4为插入节点(当前节点),这种情况调整方式是将父节点和叔叔节点都调整为黑色节点,祖父节点调整为红色,将祖父节点变为当前

【转】B树、B-树、B+树、B*树、红黑树、 二叉排序树、trie树Double Array 字典查找树简介

B  树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中:否则,如果查询关键字比结点关键字小,就进入左儿子:如果比结点关键字大,就进入右儿子:如果左儿子或右儿子的指针为空,则报告找不到相应的关键字: 如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性