linux核心紅黑樹的演算法都定義在linux-2.6.38.8/include/linux/rbtree.h和linux-2.6.38.8/lib/rbtree.c兩個檔案中。
1、結構體
[cpp]view plain
copy
print?
struct rb_node
__attribute__((aligned(sizeof(long))));
struct rb_node
__attribute__((aligned(sizeof(long))));
這裡的巧妙之處是使用成員rb_parent_color同時儲存兩種資料,一是其雙親結點的位址,另一是此結點的著色。__attribute__((aligned(sizeof(long))))屬性保證了紅黑樹中的每個結點的首位址都是32位對齊的(在32位機上),也就是說每個結點首位址的bit[1]和bit[0]都是0,因此就可以使用bit[0]來儲存結點的顏色屬性而不干擾到其雙親結點首位址的儲存。
ps: ptmalloc **中也用到這些特性,通過將一結構體進行位址對齊後,該結構體的首元素就可以節省出幾個位用作他用。這種方法可以更高效地利用記憶體空間。
ps:為什麼在rb_node中需要儲存其父親節點的首位址啊?因為核心中如果進行樹的遍歷,不可能用遞迴實現(遞迴容易造成棧溢位)。這樣做,可以更好地轉化為迭代來進行更好的樹的遍歷。
操作rb_parent_color的函式:
[cpp]view plain
copy
print?
#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 while (0) //設定紅色屬性
#define rb_set_black(r) do while (0) //設定黑色屬性
static
inline
void rb_set_parent(struct rb_node *rb, struct rb_node *p) //設定其雙親結點首位址的函式
static
inline
void rb_set_color(struct rb_node *rb, int color) //設定結點顏色屬性的函式
紅黑樹的遍歷:
4、遍歷
rb_first和rb_next函式可組成中序遍歷,即以公升序遍歷紅黑樹中的所有結點。
[cpp]view plain
copy
print?
struct rb_node *rb_first(const
struct rb_root *root)
struct rb_node *rb_next(const
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 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;
}
乙個遍歷的演示程式:
void print_rbtree(struct rb_root *tree)
ps:linux核心中將這種遍歷做成了stl迭代器的形式,從而更好地進行**的復用。
ps:感覺linux 核心中還有些 for_each巨集之類的東西,是想做成閉包的形式,也是模仿stl的思想,更好地進行**復用。
紅黑樹實現
紅黑樹 是一棵二叉搜尋樹,它在每個節點上增加了乙個儲存位來表示節點的顏色,可以是red或black。通過對任何一條從根到葉子簡單路徑上的 顏色來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近似於平衡 由於性質中紅色節點不連續,最短路徑可為全是連續黑結點,最長路徑則由於紅節點不連續,則每間隔乙個...
紅黑樹實現
按演算法導論裡的偽 用c 實現了紅黑樹。實現過程中,參考了nginx的紅黑樹實現,特別是右旋的實現,演算法導論裡沒有給出,就借鑑了nginx的實現。對比了nginx的紅黑樹實現和演算法導論裡的偽 插入基本上一樣的,刪除兩者有點差別,但思路應該是一樣的。實現過程中需要注意的是,空葉子結點一定要實現,不...
紅黑樹下 紅黑樹的實現
1.實現紅黑樹的基本思想 實際上,紅黑樹是有固定的平衡過程的 遇到什麼樣的節點分布,我們就對應怎麼去調整。只要按照這些固定的調整規則來操作,就能將乙個非平衡的紅黑樹調整成平衡的。首先,我們需要再來看一下紅黑樹的定義 在插入 刪除節點的過程中,第 三 四點要求可能會被破壞,所以 平衡調整 實際上就是把...