第一篇 linux中红黑树的具体实现及迁移,应用

来源:互联网 发布:知行合一的知的意思 编辑:程序博客网 时间:2024/05/16 10:22


这是该系列的第一篇文章,写作的目的:内心近段时间很混沌,学东西感觉很混乱,所以特开此篇用来1.有计划有目的保质保量的在循序渐进数据结构计算法

2.能够把阅读好的结构实现的一些内心真实想法呈现出来,也给自己更大的动力去完成

3.慢慢的扎扎实实的把一系列一系列的东西做好,相信会有收获

4.在完成这一系列的东西时,有所记录培养成就感,也当做对自己技术学习的一个索引

5.尽量试着尝试在github上上传有代表性的好的代码,多参与技术交流和技术论坛,防止一叶障目。

第一节   linux  rbtree一览

1.

__attribute__((aligned(sizeof(long))))//这里的代码意思是让GNU编译器设定对齐方式
2.x86是小端模式 如ox12345678存的地址可能就是
0x00000001           -- 78
0x00000002           -- 56
0x00000003           -- 34
0x00000004           -- 12
3.rbnode设置的是四字节对齐,所以parent指针的低两位总是为0,可以用来存储颜色位
4.rbtree中操作颜色位里面用到了大量的宏函数
5.http://www.tuicool.com/articles/a6j2Ib红黑树的基本介绍,及linux红黑树的迁移与小实例
6.http://blog.csdn.net/21aspnet/article/details/6729724关于字节对齐的详细介绍,可以用来理解__attribute__((aligned(sizeof(long))))
代码如下rbtree.h
/*  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  int two steps: as first thing the code must insert the element in  order as a red leaf in the tree, 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;elsereturn 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;elsereturn 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(WIN32) && !defined(__cplusplus)#define inline __inline#endif//#include <linux/kernel.h>//#include <linux/stddef.h>#define NULL 0#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#define container_of(ptr, type, member) ({                \    const typeof( ((type *)0)->member ) *__mptr = (ptr);  \    (type *)( (char *)__mptr - offsetof(type,member) );})struct rb_node{unsigned long  rb_parent_color;#defineRB_RED0#defineRB_BLACK1struct rb_node *rb_right;struct rb_node *rb_left;}   ;// __attribute__((aligned(sizeof(long))));//由于vc默认是4字节对齐所以 __attribute__((aligned(sizeof(long))))可省略    /* The alignment might seem pointless, but allegedly CRIS needs it */struct rb_root{struct rb_node *rb_node;};#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, }#definerb_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))extern void rb_insert_color(struct rb_node *, struct rb_root *);extern void rb_erase(struct rb_node *, struct rb_root *);/* Find logical next and previous nodes in a tree */extern struct rb_node *rb_next(struct rb_node *);extern struct rb_node *rb_prev(struct rb_node *);extern struct rb_node *rb_first(struct rb_root *);extern struct rb_node *rb_last(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 */

rbtree.c
/*  Red Black Trees  (C) 1999  Andrea Arcangeli <andrea@suse.de>  (C) 2002  David Woodhouse <dwmw2@infradead.org>    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/lib/rbtree.c*///#include <linux/rbtree.h>//#include <linux/module.h>#include"rbtree.h"static void __rb_rotate_left(struct rb_node *node, struct rb_root *root){struct rb_node *right = node->rb_right;struct rb_node *parent = rb_parent(node);if ((node->rb_right = right->rb_left))rb_set_parent(right->rb_left, node);right->rb_left = node;rb_set_parent(right, parent);if (parent){if (node == parent->rb_left)parent->rb_left = right;elseparent->rb_right = right;}elseroot->rb_node = right;rb_set_parent(node, right);}static void __rb_rotate_right(struct rb_node *node, struct rb_root *root){struct rb_node *left = node->rb_left;struct rb_node *parent = rb_parent(node);if ((node->rb_left = left->rb_right))rb_set_parent(left->rb_right, node);left->rb_right = node;rb_set_parent(left, parent);if (parent){if (node == parent->rb_right)parent->rb_right = left;elseparent->rb_left = left;}elseroot->rb_node = left;rb_set_parent(node, left);}void rb_insert_color(struct rb_node *node, struct rb_root *root){struct rb_node *parent, *gparent;while ((parent = rb_parent(node)) && rb_is_red(parent)){gparent = rb_parent(parent);if (parent == gparent->rb_left){{register struct rb_node *uncle = gparent->rb_right;if (uncle && rb_is_red(uncle)){rb_set_black(uncle);rb_set_black(parent);rb_set_red(gparent);node = gparent;continue;}}if (parent->rb_right == node){register struct rb_node *tmp;__rb_rotate_left(parent, root);tmp = parent;parent = node;node = tmp;}rb_set_black(parent);rb_set_red(gparent);__rb_rotate_right(gparent, root);} else {{register struct rb_node *uncle = gparent->rb_left;if (uncle && rb_is_red(uncle)){rb_set_black(uncle);rb_set_black(parent);rb_set_red(gparent);node = gparent;continue;}}if (parent->rb_left == node){register struct rb_node *tmp;__rb_rotate_right(parent, root);tmp = parent;parent = node;node = tmp;}rb_set_black(parent);rb_set_red(gparent);__rb_rotate_left(gparent, root);}}rb_set_black(root->rb_node);}//EXPORT_SYMBOL(rb_insert_color);static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,     struct rb_root *root){struct rb_node *other;while ((!node || rb_is_black(node)) && node != root->rb_node){if (parent->rb_left == node){other = parent->rb_right;if (rb_is_red(other)){rb_set_black(other);rb_set_red(parent);__rb_rotate_left(parent, root);other = parent->rb_right;}if ((!other->rb_left || rb_is_black(other->rb_left)) &&    (!other->rb_right || rb_is_black(other->rb_right))){rb_set_red(other);node = parent;parent = rb_parent(node);}else{if (!other->rb_right || rb_is_black(other->rb_right)){struct rb_node *o_left;if ((o_left = other->rb_left))rb_set_black(o_left);rb_set_red(other);__rb_rotate_right(other, root);other = parent->rb_right;}rb_set_color(other, rb_color(parent));rb_set_black(parent);if (other->rb_right)rb_set_black(other->rb_right);__rb_rotate_left(parent, root);node = root->rb_node;break;}}else{other = parent->rb_left;if (rb_is_red(other)){rb_set_black(other);rb_set_red(parent);__rb_rotate_right(parent, root);other = parent->rb_left;}if ((!other->rb_left || rb_is_black(other->rb_left)) &&    (!other->rb_right || rb_is_black(other->rb_right))){rb_set_red(other);node = parent;parent = rb_parent(node);}else{if (!other->rb_left || rb_is_black(other->rb_left)){register struct rb_node *o_right;if ((o_right = other->rb_right))rb_set_black(o_right);rb_set_red(other);__rb_rotate_left(other, root);other = parent->rb_left;}rb_set_color(other, rb_color(parent));rb_set_black(parent);if (other->rb_left)rb_set_black(other->rb_left);__rb_rotate_right(parent, root);node = root->rb_node;break;}}}if (node)rb_set_black(node);}void rb_erase(struct rb_node *node, struct rb_root *root){struct rb_node *child, *parent;int color;if (!node->rb_left)child = node->rb_right;else if (!node->rb_right)child = node->rb_left;else{struct rb_node *old = node, *left;node = node->rb_right;while ((left = node->rb_left) != NULL)node = left;child = node->rb_right;parent = rb_parent(node);color = rb_color(node);if (child)rb_set_parent(child, parent);if (parent == old) {parent->rb_right = child;parent = node;} elseparent->rb_left = child;node->rb_parent_color = old->rb_parent_color;node->rb_right = old->rb_right;node->rb_left = old->rb_left;if (rb_parent(old)){if (rb_parent(old)->rb_left == old)rb_parent(old)->rb_left = node;elserb_parent(old)->rb_right = node;} elseroot->rb_node = node;rb_set_parent(old->rb_left, node);if (old->rb_right)rb_set_parent(old->rb_right, node);goto color;}parent = rb_parent(node);color = rb_color(node);if (child)rb_set_parent(child, parent);if (parent){if (parent->rb_left == node)parent->rb_left = child;elseparent->rb_right = child;}elseroot->rb_node = child; color:if (color == RB_BLACK)__rb_erase_color(child, parent, root);}//EXPORT_SYMBOL(rb_erase);/* * This function returns the first node (in sort order) of the tree. */struct rb_node *rb_first(struct rb_root *root){struct rb_node*n;n = root->rb_node;if (!n)return NULL;while (n->rb_left)n = n->rb_left;return n;}//EXPORT_SYMBOL(rb_first);struct rb_node *rb_last(struct rb_root *root){struct rb_node*n;n = root->rb_node;if (!n)return NULL;while (n->rb_right)n = n->rb_right;return n;}//EXPORT_SYMBOL(rb_last);struct rb_node *rb_next(struct rb_node *node){struct rb_node *parent;if (rb_parent(node) == node)return NULL;/* If we have a right-hand child, go down and then left as far   as we can. */if (node->rb_right) {node = node->rb_right; while (node->rb_left)node=node->rb_left;return node;}/* No right-hand children.  Everything down and left is   smaller than us, so any 'next' node must be in the general   direction of our parent. Go up the tree; any time the   ancestor is a right-hand child of its parent, keep going   up. First time it's a left-hand child of its parent, said   parent is our 'next' node. */while ((parent = rb_parent(node)) && node == parent->rb_right)node = parent;return parent;}//EXPORT_SYMBOL(rb_next);struct rb_node *rb_prev(struct rb_node *node){struct rb_node *parent;if (rb_parent(node) == node)return NULL;/* If we have a left-hand child, go down and then right as far   as we can. */if (node->rb_left) {node = node->rb_left; while (node->rb_right)node=node->rb_right;return node;}/* No left-hand children. Go up till we find an ancestor which   is a right-hand child of its parent */while ((parent = rb_parent(node)) && node == parent->rb_left)node = parent;return parent;}//EXPORT_SYMBOL(rb_prev);void rb_replace_node(struct rb_node *victim, struct rb_node *_new,     struct rb_root *root){struct rb_node *parent = rb_parent(victim);/* Set the surrounding nodes to point to the replacement */if (parent) {if (victim == parent->rb_left)parent->rb_left = _new;elseparent->rb_right = _new;} else {root->rb_node = _new;}if (victim->rb_left)rb_set_parent(victim->rb_left, _new);if (victim->rb_right)rb_set_parent(victim->rb_right, _new);/* Copy the pointers/colour from the victim to the replacement */*_new = *victim;}//EXPORT_SYMBOL(rb_replace_node);

rbtreetest.c

// rbtreeTest.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "rbtree.c"#include <string.h>#include <malloc.h>#define FALSE 0;#define TRUE 1;struct mytype{char* keystring;rb_node node;};#define list_entry(ptr, type, member) \        ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))struct mytype *my_search(struct rb_root *root, char *string){  struct rb_node *node = root->rb_node;  while (node)  {struct mytype *data = list_entry(node, struct mytype, node);int result = strcmp(string, data->keystring);if (result < 0)  node = node->rb_left;else if (result > 0)  node = node->rb_right;else  return data;  }  return NULL;}int my_insert(struct rb_root *root, struct mytype *data){  struct rb_node **_new = &(root->rb_node), *parent = NULL;  /* Figure out where to put new node */  while (*_new)  {    struct mytype *_this = list_entry(*_new, struct mytype, node);//{                \ //   const typeof( ((type *)0)->member ) *__mptr = (ptr);  \ //   (type *)( (char *)__mptr - offsetof(type,member) );}    int result = strcmp(data->keystring, _this->keystring);    parent = *_new;    if (result < 0)      _new = &((*_new)->rb_left);    else if (result > 0)      _new = &((*_new)->rb_right);    else      return FALSE;  }  /* Add new node and rebalance tree. */  rb_link_node(&data->node, parent, _new);  rb_insert_color(&data->node, root);  return TRUE;}//struct mytype *data = my_search(&mytree, "walrus");//if (data)//{//  rb_erase(&data->node, &mytree);//  myfree(data);//}int _tmain(int argc, _TCHAR* argv[]){//rb_root* root=(rb_root*)malloc(sizeof(rb_root));//root->rb_node=(struct rb_node*)malloc(sizeof(struct rb_node));//root->rb_node->rb_left=(struct rb_node*)malloc(sizeof(struct rb_node));//root->rb_node->rb_left->rb_left=nullptr;//root->rb_node->rb_right=(struct rb_node*)malloc(sizeof(struct rb_node));//root->rb_node->rb_left->rb_right=nullptr;rb_root* root=(rb_root*)malloc(sizeof(rb_root));struct mytype* first_mytype=(struct mytype*)malloc(sizeof(struct mytype));root->rb_node=&first_mytype->node;first_mytype->keystring="nihao";root->rb_node->rb_left=nullptr;root->rb_node->rb_right=nullptr;//struct rb_node my_node=(struct rb_node*)malloc(sizeof(struct rb_node));struct mytype* my=(struct mytype*)malloc(sizeof(struct mytype));my->keystring="zhangsan";struct mytype* my2=(struct mytype*)malloc(sizeof(struct mytype));my2->keystring="lisi";my_insert(root,my);my_insert(root,my2);char* s="lisi1";struct mytype* my1 =my_search(root,s);printf("shi%s",my1->keystring);return 0;}

0 0
原创粉丝点击