存儲稀疏的數據集而且將用一個大整數進行插入,刪除,查找的操作基礎。而hash表
並不是以某種排序順序進行存儲,而且必須指定大小和hash函數。
RB樹與AVL樹很相似,但是比AVL樹有更好的插入和刪除最壞情況的時間複雜度,以及
O(logn)的最壞查找時間複雜度。
引用:
在Linux中有很多地方用到了RD樹。anticipatory, deadline, 和CFQ I/O調度都使用
的是RB樹進行請求跟蹤,還有CD/DVD驅動的包管理也是如此。
高精度計時器(high-resolution timer)使用RB樹組織定時請求。
EXT3文件系統也使用RB樹來管理目錄。
虛擬存儲管理系統也是有RB樹進行VMAs(Virtual Memory Areas)的管理。
當然還有文件描述符,密碼鑰匙,“等級令牌桶”調度的網絡數據包都是用RB數據進
行組織和管理的。
相關資料:
Linux WeeklyNews article on red-black trees
http://lwn.net/Articles/184495/
Wikipediaentry on red-black trees
http://en.wikipedia.org/wiki/Red-black_tree
可見RB樹(紅黑樹)在Linux內核中的重要性。
Linux內核的RB樹實現
---------------------------------------
在Linux內核源代碼中rb樹的實現在lib/rbtree.c文件中,可以通過
#include"linux/rbtree.h"進行使用。
在Linux內核中的RB樹實現與傳統的實現方式有些不同。它對針對內核對速度的需要做
了些優化。每一個rb_node節點是嵌入在用RB樹進行組織的數據結構中,而不是用
rb_node指針進行數據結構的組織。
創建一棵RB樹
---------------------
在RB樹裏的數據節點包含了一個rb_node數據結構節點。如下:
structmytype {
struct rb_node node;
char *keystring;
};
可以通過container_of宏取得包含了rb_node的數據結構。也可以通過
rb_entry(node,type,member)取得。
其實是#definerb_entry(node,type,member) container_of(node,type,member)
這裏順便說一下如何通過container_of取得包含rb_node的數據結構指針:
在Linux內核代碼裏有這樣的宏定義:
#definecontainer_of(ptr, type, member) ({\
consttypeof( ((type *)0)->member ) *__mptr =(ptr);\
(type *)((char *)__mptr - offsetof(type,member) );})
#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)
那麼對於structmytype,如何通過其成員node來取得走首地址呢:
我們肯定已經知道node的地址,假設爲pnode;
structmytype* x = rb_entry(pnode, struct mytype, node);
意思是,取得pnode所被包含的數據結構對象的首地址,pnode是指向struct mytype的
成員node的指針。
宏替換完後就是這個樣子:
({
const typeof( ((struct mytype *)0)->node ) *__mptr =(pnode);
(struct mytype *)((char *)__mptr-((size_t)&((structmytype*)0)->node));
})
typeof取得struct mytype中node成員的類型,用這個類型定義一個新的指針,把
pnode的值賦給它,在這裏起到了類型檢查的作用。
offsetof(type,member)是取得member在type對象中相對於此對象首地址的偏移量。
那麼用__mptr減去這個偏移量就得到了type對象的起始地址。也就得到了把rb_node
作爲嵌入的管理數據結構的對象起始地址。
x = y -offset
----------<--x
| |
| |
|--------|<--offset <--y
|