项目需要写了一个,内核红黑数代码的封装使用

本文详细介绍了 Red-Black 树的实现和使用方法,包括内部结构、搜索、插入、删除等操作,以及如何在用户空间的 C 程序中应用。通过示例代码展示了如何自定义插入和搜索核心逻辑,以避免回调函数并提高性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
 * =============================================================================
 *
 *       Filename:  rbtree.h
 *
 *    Description:  rbtree(Red-Black tree) implementation adapted from linux
 *                  kernel thus can be used in userspace c program.
 *
 *        Created:  09/02/2012 11:36:11 PM
 *
 *         Author:  Fu Haiping (forhappy), haipingf@gmail.com
 *        Company:  ICT ( Institute Of Computing Technology, CAS )
 *
 * =============================================================================
 */

/*
  Red Black Trees
  (C) 1999  Andrea Arcangeli <andrea@suse.de>
  
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  linux/include/linux/rbtree.h

  To use rbtrees you'll have to implement your own insert and search cores.
  This will avoid us to use callbacks and to drop drammatically performances.
  I know it's not the cleaner way,  but in C (not in C++) to get
  performances and genericity...

  Some example of insert and search follows here. The search is a plain
  normal search over an ordered tree. The insert instead must be implemented
  in two steps: First, the code must insert the element in order as a red leaf
  in the tree, and then the support library function rb_insert_color() must
  be called. Such function will do the not trivial work to rebalance the
  rbtree, if necessary.

-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
						 unsigned long offset)
{
	struct rb_node * n = inode->i_rb_page_cache.rb_node;
	struct page * page;

	while (n)
	{
		page = rb_entry(n, struct page, rb_page_cache);

		if (offset < page->offset)
			n = n->rb_left;
		else if (offset > page->offset)
			n = n->rb_right;
		else
			return page;
	}
	return NULL;
}

static inline struct page * __rb_insert_page_cache(struct inode * inode,
						   unsigned long offset,
						   struct rb_node * node)
{
	struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
	struct rb_node * parent = NULL;
	struct page * page;

	while (*p)
	{
		parent = *p;
		page = rb_entry(parent, struct page, rb_page_cache);

		if (offset < page->offset)
			p = &(*p)->rb_left;
		else if (offset > page->offset)
			p = &(*p)->rb_right;
		else
			return page;
	}

	rb_link_node(node, parent, p);

	return NULL;
}

static inline struct page * rb_insert_page_cache(struct inode * inode,
						 unsigned long offset,
						 struct rb_node * node)
{
	struct page * ret;
	if ((ret = __rb_insert_page_cache(inode, offset, node)))
		goto out;
	rb_insert_color(node, &inode->i_rb_page_cache);
 out:
	return ret;
}
-----------------------------------------------------------------------
*/

#ifndef	_LINUX_RBTREE_H
#define	_LINUX_RBTREE_H

#if defined(container_of)
  #undef container_of
  #define container_of(ptr, type, member) ({			\
        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
        (type *)( (char *)__mptr - offsetof(type,member) );})
#else
  #define container_of(ptr, type, member) ({			\
        const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
        (type *)( (char *)__mptr - offsetof(type,member) );})
#endif

#if defined(offsetof)
  #undef offsetof
  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else 
  #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif

#undef NULL
#if defined(__cplusplus)
  #define NULL 0
#else
  #define NULL ((void *)0)
#endif

struct rb_node
{
	unsigned long  rb_parent_color;
#define	RB_RED		0
#define	RB_BLACK	1
	struct rb_node *rb_right;
	struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
    /* The alignment might seem pointless, but allegedly CRIS needs it */

struct rb_root
{
	//struct rb_node *rb_node;
	struct rb_node *rb_node; //上面需要修改成这样
	// add three domain
	void *pcurrent; //指向最新插入记录
	int cols; //代表列数
	int records;//当前表格的记录数
};


#define rb_parent(r)   ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r)   ((r)->rb_parent_color & 1)
#define rb_is_red(r)   (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r)  do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r)  do { (r)->rb_parent_color |= 1; } while (0)

static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
	rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
	rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}

//#define RB_ROOT	(struct rb_root) { NULL,NULL,33,0 }  //修改
#define	rb_entry(ptr, type, member) container_of(ptr, type, member)

#define RB_EMPTY_ROOT(root)	((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node)	(rb_parent(node) == node)
#define RB_CLEAR_NODE(node)	(rb_set_parent(node, node))

static inline void rb_init_node(struct rb_node *rb)
{
	rb->rb_parent_color = 0;
	rb->rb_right = NULL;
	rb->rb_left = NULL;
	RB_CLEAR_NODE(rb);
}

extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);

typedef void (*rb_augment_f)(struct rb_node *node, void *data);

extern void rb_augment_insert(struct rb_node *node,
			      rb_augment_f func, void *data);
extern struct rb_node *rb_augment_erase_begin(struct rb_node *node);
extern void rb_augment_erase_end(struct rb_node *node,
				 rb_augment_f func, void *data);

/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(const struct rb_node *);
extern struct rb_node *rb_prev(const struct rb_node *);
extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);

/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
			    struct rb_root *root);

static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
				struct rb_node ** rb_link)
{
	node->rb_parent_color = (unsigned long )parent;
	node->rb_left = node->rb_right = NULL;

	*rb_link = node;
}

#endif	/* _LINUX_RBTREE_H */


//main.c
<pre name="code" class="plain">/*
 * =============================================================================
 *
 *       Filename:  rbtree-tst.c
 *
 *    Description:  rbtree testcase.
 *
 *        Created:  05/26/2014 
 *
 *         Author:  JackyLau, liuyongvs@gmail.com
 *        Company:  USTC(University of Science and Technology)
 *
 * =============================================================================
 */

#include "rbtree.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define MAX_RECORDS  10

struct mynode {
  	struct rb_node node;
  	char *string;  //表示节点号
	//add three domain
	int from;
	int to;
	void *pdata;//表格指针
};

//struct rb_root mytree = RB_ROOT;
struct rb_root mytree;
void my_createtable(int cols)
{
	mytree.rb_node=NULL;
	mytree.pcurrent=NULL;// mytree.rb_node
	mytree.cols=cols;
	mytree.records=0;
//	return 
}
struct mynode * search(struct rb_root *root, char *string)
{
  	struct rb_node *node = root->rb_node;

  	while (node) {
  		struct mynode *data = container_of(node, struct mynode, node);
		int result;

		result = strcmp(string, data->string);

		if (result < 0)
  			node = node->rb_left;
		else if (result > 0)
  			node = node->rb_right;
		else
  			return data;
	}
	return NULL;
}

struct mynode * my_search(struct rb_root *root, int id)
{
	//int id=records/10;
	char str[10];
	sprintf(str, "%d", id);
	struct mynode *data=search(&mytree,str);
	return data;

}

/*
int my_appendrecords(struct rb_root *root, char *record)
{
	if(root->records % MAX_RECORDS==9) // 该表已满,需要另一个结点
	{
		my_insert(root, );
	}
	//....
}

*/
int insert(struct rb_root *root, struct mynode *data)
{

  	struct rb_node **new = &(root->rb_node), *parent = NULL;

  	/* Figure out where to put new node */
  	while (*new) {
  		struct mynode *this = container_of(*new, struct mynode, node);
  		int result = strcmp(data->string, this->string);

		parent = *new;
  		if (result < 0)
  			new = &((*new)->rb_left);
  		else if (result > 0)
  			new = &((*new)->rb_right);
  		else
  			return 0;
  	}

  	/* Add new node and rebalance tree. */
  	rb_link_node(&data->node, parent, new);
  	rb_insert_color(&data->node, root);

	return 1;
}

int my_insert(struct rb_root *root, int id)
{
	struct mynode *node;
	node= (struct mynode *)malloc(sizeof(struct mynode));
	node->string = (char *)malloc(sizeof(char) * 10);
	sprintf(node->string, "%d", id);		
	if( insert(&mytree, node) )
	{
		root->pcurrent=node;
		node->from=root->records;
		node->to=node->from;
		//node->pdata=

		return 1;
	}
	else
		return 0;
}


void my_free(struct mynode *node)
{
	if (node != NULL) 
	{
		if (node->string != NULL) 
		{
			free(node->string);
			node->string = NULL;
		}
		if (node->pdata != NULL) 
		{
		//Table *table=node->pdata;
		//DestroyTable(table);
		}
		free(node);
		node = NULL;
	}
}


void my_destroytree(struct rb_node *node)
{
  	if (node) 
	{
		my_destroytree(node->rb_left);
		my_destroytree(node->rb_right);	
  		struct mynode *data = container_of(node, struct mynode, node); 
		my_free(data);			
	}

}

/*
void mydestroytable(Table *table)
{

}
*/


void my_delete(struct rb_root *root, int id)
{
    struct mynode *data = my_search(root, id);
    if (!data) { 
	fprintf(stderr, "Not found %d.\n", id);
	return;
    }
    
    rb_erase(&data->node, root);
    my_free(data);
}

void my_printrbtree(struct rb_root *tree)
{
    struct rb_node *node;   
    for (node = rb_first(tree); node; node = rb_next(node))
	{
	if(rb_entry(node, struct mynode, node)->string==NULL)
	  return ;
    	printf("key = %s\n", rb_entry(node, struct mynode, node)->string);
	}
    printf("\n");
}

#define NUM_NODES  32

int main()
{
	my_createtable(33);

	/* *insert */	
	int i;
	for(i=0; i< NUM_NODES; i++)
	{
		my_insert(&mytree, i);
	}
	
	printf("search all nodes: \n");
	my_printrbtree(&mytree);

	/* *delete */
	printf("delete node 20: \n");
	my_delete(&mytree, 20);
	
	/* *delete again*/
	printf("delete node 10: \n");
	my_delete(&mytree, 10);

	/* *delete once again*/
	printf("delete node 15: \n");
	my_delete(&mytree, 15);

	/* *search again*/
	printf("search again:\n");
	my_printrbtree(&mytree);


	my_destroytree(mytree.rb_node);
	printf("DestroyTree Success!.\n");

	
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值