/*
* =============================================================================
*
* 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;
}