当前位置: 首页 > news >正文

交互网站开发培训东莞主页网站制作

交互网站开发培训,东莞主页网站制作,成都室内装修设计培训,建设电子商务网站目的红黑树(rbtree)在linux内核中使用非常广泛,cfs调度任务管理#xff0c;vma管理等。本文不会涉及关于红黑树插入和删除时的各种case的详细描述,感兴趣的读者可以查阅其他资料。本文主要聚焦于linux内核中经典rbtree和augment-rbtree操作接口的说明。 1、基本概念 二叉树:每个…红黑树(rbtree)在linux内核中使用非常广泛,cfs调度任务管理vma管理等。本文不会涉及关于红黑树插入和删除时的各种case的详细描述,感兴趣的读者可以查阅其他资料。本文主要聚焦于linux内核中经典rbtree和augment-rbtree操作接口的说明。 1、基本概念 二叉树:每个结点最多2棵子树,无其它限制了。 二叉查找树(二叉排序树/二叉搜索树):首先它是二叉树,左子树上所有结点的值小于它根结点的值,右子树上所有结点的值大于它根结点的值(递归定义). 二叉平衡树:也称为平衡二叉树,它是平衡二叉搜索树的简称。首先它是二叉搜索树,其次它是平衡的,即它的每一个结点的左子树的高度和右子树的高度差至多为1。 红黑树性质: 红黑树是每个节点都带有颜色属性的二叉查找树颜色为红色或黑色。除二叉查找树强制一般要求以外对于任何有效的红黑树增加了如下的额外要求: 性质1. 节点是红色或黑色。 性质2. 根是黑色。 性质3. 所有叶子都是黑色叶子是NULL节点。 性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。 * red-black trees properties:  http://en.wikipedia.org/wiki/Rbtree * *  1) A node is either red or black *  2) The root is black *  3) All leaves (NULL) are black *  4) Both children of every red node are black *  5) Every simple path from root to leaves contains the same number of black nodes. * *  4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two *  consecutive red nodes in a path and every red node is therefore followed by *  a black. So if B is the number of black nodes on every simple path (as per *  5), then the longest possible path due to 4 is 2B. * *  We shall indicate color with case, where black nodes are uppercase(大写字母) and red nodes will be lowercase(小写字母). *  Unknown color nodes shall be drawn as red within parentheses and have some accompanying text comment. linux内核中的红黑树分为两类,一类是经典的红黑树,用于存放key/value键值对另一类是增强型红黑树(VMA是内核中典型的augment-rbtree)。 增强型rbtree是一种在每个节点中存储了“一些”额外数据的rbtree其中节点N的额外数据必须是根为N的子树中所有节点内容的函数。 这些数据可用于为rbtree增加一些新功能。增强rbtree是建立在基本rbtree基础设施之上的可选功能。 需要此特性的rbtree用户在插入和删除节点时必须使用用户提供的增强回调调用增强函数。 注意内核红黑树的实现将部分工作留给了用户来实现:用户需要编写自己的树搜索和插入函数调用所提供的rbtree函数,锁也留给rbtree代码的用户。 2、数据结构 /*linux内核中,rbtree作为通用数据结构类似链表是嵌入到用户数据结构内部,在用户数据结构中存放自己的数据*/ struct rb_node {/*父节点由于struct rb_node是long对齐,所以其地址低3-0bit或7-0bit未使用,低2位被用来作为颜色标志使用*/unsigned long __rb_parent_color;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_node为long字节对齐,其地址最少也是4字节对齐,所以其成员__rb_parent_color用于存放其parent的地址,同时低2bit可以存放自身的----颜色属性。/*根节点*/ struct rb_root {struct rb_node *rb_node; };/*节点颜色默认插入节点为红色*/ #define RB_RED 0 #define RB_BLACK 1/*父节点地址, ~3 去掉颜色标志位*/ #define rb_parent(r) ((struct rb_node *)((r)-__rb_parent_color ~3))#define RB_ROOT (struct rb_root) { NULL, } #define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL }#define __rb_parent(pc) ((struct rb_node *)(pc ~3))/*pc节点的颜色*/ #define __rb_color(pc) ((pc) 1) #define __rb_is_black(pc) __rb_color(pc) #define __rb_is_red(pc) (!__rb_color(pc))/*rb-__rb_parent_color的颜色*/ #define rb_color(rb) __rb_color((rb)-__rb_parent_color) #define rb_is_red(rb) __rb_is_red((rb)-__rb_parent_color) #define rb_is_black(rb) __rb_is_black((rb)-__rb_parent_color)/*返回内嵌struct rb_node的数据结构*/ #define rb_entry(ptr, type, member) container_of(ptr, type, member)#define RB_EMPTY_ROOT(root) (READ_ONCE((root)-rb_node) NULL)/* empty nodes are nodes that are known not to be inserted in an rbtree */ #define RB_EMPTY_NODE(node) \((node)-__rb_parent_color (unsigned long)(node))/*注意,这里是赋值操作*/ #define RB_CLEAR_NODE(node) \((node)-__rb_parent_color (unsigned long)(node)) 3、接口说明 3.1、rbtree插入红黑树节点 3.1.1、经典rbtree插入红黑树节点 在将数据插入rbtree之前需要用户实现查找函数,查找插入节点应该插入到rbtree root中的位置,建立链接后,才能将其插入到root中 系统无法知道用户数据存放规则,将节点存放到rbtree中的位置的查找工作交给用户来处理。 通过rb_link_node(...)接口设置node要被插入到parent下面,建立位置链接关系 static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,struct rb_node **rb_link) {/*设置node__rb_parent_color的值,颜色属性为红色*/node-__rb_parent_color (unsigned long)parent; node-rb_left node-rb_right NULL;*rb_link node; }在树中插入数据包括首先搜索插入新节点的位置然后插入节点并重新平衡(“重新上色”)树。 void rb_insert_color(struct rb_node *node, struct rb_root *root) {__rb_insert(node, root, dummy_rotate); } 节点插入的工作交给__rb_insert来处理。下面是__rb_insert函数原型: static __always_inline void __rb_insert(struct rb_node *node, struct rb_root *root,void (*augment_rotate)(struct rb_node *old, struct rb_node *new))其中augment_rotate函数指针传入旋转回调函数,经典红黑树中未使用传入哑旋转回调函数dummy_rotate;经典红黑树只是存储节点之间的顺序关系,无其他额外信息,所以其struct rb_augment_callbacks 增强回调函数全部实现为空 /** Non-augmented rbtree manipulation functions.(非增强红黑树操作功能函数)** We use dummy augmented callbacks here, and have the compiler optimize them* out of the rb_insert_color() and rb_erase() function definitions.*/static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {}static const struct rb_augment_callbacks dummy_callbacks {dummy_propagate, dummy_copy, dummy_rotate };/** Please note - only struct rb_augment_callbacks and the prototypes for* rb_insert_augmented() and rb_erase_augmented() are intended to be public.* The rest are implementation details you are not expected to depend on.** See Documentation/rbtree.txt for documentation and samples.*/struct rb_augment_callbacks {void (*propagate)(struct rb_node *node, struct rb_node *stop);void (*copy)(struct rb_node *old, struct rb_node *new);void (*rotate)(struct rb_node *old, struct rb_node *new); }; 对于augment-rbtree(增强红黑树)rb_augment_callbacks的定义可以通过下面的宏来实现 /*这个宏定义的内容比较长,定义了augment回调函数接口以及对应的struct rb_augment_callbacks rbname 结构体*/ #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \rbtype, rbaugmented, rbcompute) \ static inline void \ rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ { \while (rb ! stop) { \rbstruct *node rb_entry(rb, rbstruct, rbfield); \rbtype augmented rbcompute(node); \if (node-rbaugmented augmented) \break; \node-rbaugmented augmented; \rb rb_parent(node-rbfield); \} \ } \ static inline void \ rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ { \rbstruct *old rb_entry(rb_old, rbstruct, rbfield); \rbstruct *new rb_entry(rb_new, rbstruct, rbfield); \new-rbaugmented old-rbaugmented; \ } \ static void \ rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ { \rbstruct *old rb_entry(rb_old, rbstruct, rbfield); \rbstruct *new rb_entry(rb_new, rbstruct, rbfield); \new-rbaugmented old-rbaugmented; \old-rbaugmented rbcompute(old); \ } \ rbstatic const struct rb_augment_callbacks rbname { \rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ }; 3.1.2、augment-rbtree(增强红黑树)插入红黑树节点 在插入时用户必须更新通向插入节点的路径上的增强信息然后像往常一样调用rb_link_node()和rb_augment_inserted()而不是通常的rb_insert_color()调用。 如果rb_augment_inserts()重新平衡了rbtree它将回调为用户提供的函数以更新受影响子树上的增强信息。 /** Fixup the rbtree and update the augmented information when rebalancing.** On insertion, the user must update the augmented information on the path* leading to the inserted node, then call rb_link_node() as usual and* rb_augment_inserted() instead of the usual rb_insert_color() call.* If rb_augment_inserted() rebalances the rbtree, it will callback into* a user provided function to update the augmented information on the* affected subtrees.*/ static inline void rb_insert_augmented(struct rb_node *node, struct rb_root *root,const struct rb_augment_callbacks *augment) {__rb_insert_augmented(node, root, augment-rotate); }/** Augmented rbtree manipulation functions.** This instantiates the same __always_inline functions as in the non-augmented* case, but this time with user-defined callbacks.*/void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) {__rb_insert(node, root, augment_rotate); } 和经典红黑树插入节点操作一样,最后的后都是留给__rb_insert来处理的。区别在于需要提供augmet-rotate的实现。 3.2、rbtree删除红黑树节点 3.2.1、经典rbtree删除红黑树节点 void rb_erase(struct rb_node *node, struct rb_root *root) {struct rb_node *rebalance;rebalance __rb_erase_augmented(node, root, dummy_callbacks);if (rebalance)____rb_erase_color(rebalance, root, dummy_rotate); }/* Fast replacement of a single node without remove/rebalance/add/rebalance */ 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 */__rb_change_child(victim, new, parent, root);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; }3.2.2、augment-rbtree(增强红黑树)删除红黑树节点 当擦除节点时用户必须调用rb_erase_augmented()而不是rb_erase()。Rb_erase_augmented()回调用户提供的函数来更新受影响子树上的增强信息。 static __always_inline void rb_erase_augmented(struct rb_node *node, struct rb_root *root,const struct rb_augment_callbacks *augment) {struct rb_node *rebalance __rb_erase_augmented(node, root, augment);if (rebalance)__rb_erase_color(rebalance, root, augment-rotate); } 3.3、rbtree节点遍历 /*如果rbtree中的节点是按顺存放的话,rb_first返回最小值节点*/ struct rb_node *rb_first(const 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; }/*如果rbtree中的节点是按顺存放的话,rb_last返回最大值节点*/ struct rb_node *rb_last(const 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; }/*如果rbtree中的节点是按顺存放的话,rb_next返回值比node节点值大的节点*/ struct rb_node *rb_next(const struct rb_node *node) {struct rb_node *parent;if (RB_EMPTY_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大*/node node-rb_right;while (node-rb_left) /*一直寻找左子树*/nodenode-rb_left;return (struct rb_node *)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 its a left-hand child of its* parent, said parent is our next node.*//*node无右子树且node的parent存在:1、如果node为parent的左节点,则返回parent(parent比node大);2、node为其parent的右节点(parent比node小),则继续递归往上找(如果一直为右节点,表明node是以当前parent为root的这棵子树上的最大值),直到找到node为parent的左节点时返回其parent(parent比左子树所以节点都大)*/while ((parent rb_parent(node)) node parent-rb_right)node parent;return parent; /*这里返回的是parent*/ }/*如果rbtree中的节点是按顺存放的话,rb_next返回值比node节点值小的节点*/ struct rb_node *rb_prev(const struct rb_node *node) {struct rb_node *parent;if (RB_EMPTY_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小*/node node-rb_left; while (node-rb_right) /*一直找右子树*/nodenode-rb_right;return (struct rb_node *)node;}/** No left-hand children. Go up till we find an ancestor which* is a right-hand child of its parent.*//*node无左子树且node的parent存在1、如果node为parent的右节点,则返回parent(parent比node小) 2、node为其parent的左节点(parent比node大),则继续递归往上找,(如果一直为左节点,表明node是以当前parent为root的这棵子树上的最小值),直到找到node为parent的右节点时返回其parent(parent比右子树所以节点都小)*/while ((parent rb_parent(node)) node parent-rb_left)node parent;return parent; /*这里返回的是parent*/ } 上面四个宏可以用于遍历红黑树中的节点: for (node rb_first(mytree); node; node rb_next(node)){ ... }
http://www.w-s-a.com/news/582437/

相关文章:

  • 动态做网站网站开发语言查询 蔡学镛
  • 莆田网站建设创意自助建站英文
  • cms系统创建静态网站龙岗网站建设哪家好
  • 自己做的网站被封了邢台规划局网站建设
  • 网站建设项目合同wordpress主题没法用
  • 个旧市哪里有做网站wordpress内页php页面
  • 程序员接活的平台网站互联网平台建设方案
  • 网站安全建设模板深圳企业管理咨询公司
  • 做网站 还是淘宝店wordpress分类链接后加
  • wordpress腾讯云 COSseo内容优化心得
  • 特价旅游机票网站建设i营销
  • 如何成立网站深圳创业项目
  • 建设商业网站惠州网站建设推荐乐云seo
  • 如何申请免费域名做网站免费推广神器
  • 自媒体人专用网站安岳网站建设
  • 特乐网站建设做网站推广要多少钱
  • 山东省建设安全生产协会网站义乌跨境电商公司前十名
  • 做网站优化就是发文章吗起飞页自助建站平台的特点
  • 做网站还是做app好慈溪机械加工网
  • 上传下载文件网站开发的php源码腾讯企点
  • 给分管领导网站建设情况汇报怎么写网络运营的岗位职责及任职要求
  • 电线电缆技术支持中山网站建设广告设计培训学校有哪些
  • 如何禁止通过ip访问网站wordpress无法调用主题布局和图片
  • 江西建设工程信息网站重庆网站推广大全
  • 南浔区住房城乡建设局网站网页设计基础学什么
  • 萧山做网站的企业网站建设 西安
  • 江西省城乡建设厅网站百度站长资源平台
  • 本地搭建linux服务器做网站免费查企业信息查询
  • 电商网站建设与运营网上购物哪个网站最好
  • 做app做网站从何学起网站设计需要什么证