1. 程式人生 > >linux核心紅黑樹運用小例項

linux核心紅黑樹運用小例項

linux核心版本linux-3.10.36
在linux核心原始碼中,紅黑樹是一個比較獨立的模組,很容易將其剝離出來,拿到應用層使用。

結構

linux核心的rb_node結構體

struct rb_node {
    unsigned long  __rb_parent_color;
    struct rb_node *rb_right;
    struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
rb_parent_color這個域其實同時包含了顏色資訊以及父親節點的指標,因為該域是一個long
的型別,需要大小為sizeof(long)的對齊,那麼在一般的32位機器上,其後兩位的數值永遠是0,於是可以拿其中的一位來表示顏色。事實上,這裡就是使用了最低位來表示顏色資訊

根節點指標

struct rb_root {
    struct rb_node *rb_node;
};

介面

可以通過呼叫rb_replace_node來替換一個節點,但是替換完成後並不會對紅黑樹做任何調整,所以如果新節點的值與被替換的值有所不同時,可能會出現問題。

void rb_replace_node(struct rb_node *old, struct rb_node *new, struct
rb_root *tree);

插入與刪除

extern void rb_insert_color(struct rb_node *, struct rb_root *);//對新插入的節點著色,並修正紅黑樹使其達到平衡
extern void rb_erase(struct rb_node *, struct rb_root *);

插入節點時需要把新節點指向其父親節點,通過該函式完成

static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
                struct
rb_node ** rb_link)

rb_entry僅僅是container_of的封裝而已

#define rb_entry(ptr, type, member) container_of(ptr, type, member)

其它介面在下面的程式碼中有所解釋

例子

arvik寫了一個以mac為索引的紅黑樹小例子,裡面包括增,刪,查,銷燬幾個操作,供大家參考。如下:
標頭檔案

/****************************
* author:           arvik
* blog:             http://blog.csdn.net/u012819339
* email:            [email protected]
* kernel: linux-3.10.36
****************************/
#include <linux/string.h>
#include <linux/rbtree.h>
#include <linux/types.h>  
#include <linux/slab.h>

#define IPV4_MAC_LEN    6
typedef struct user_rb_s
{
    struct rb_node user_node;

    uint8_t umac[IPV4_MAC_LEN];
}user_rb_t;

#define mac_cmp(smac, dmac)     memcmp(smac, dmac, IPV4_MAC_LEN)

/*
申請記憶體存放節點
*/
user_rb_t *create_user_node(uint8_t *mac)
{
    user_rb_t *node;
    node = (user_rb_t *)kmalloc(sizeof(user_rb_t), GFP_ATOMIC);
    if(node == NULL)
        return node;

    memset(node, 0, sizeof(user_rb_t));
    memcpy(node->umac, mac, IPV4_MAC_LEN);
    return node;
}

/*
描述:查詢節點
返回:節點指標
*/
user_rb_t   *user_rb_find(struct rb_root *root, uint8_t *umac)
{
    struct rb_node *node = root->rb_node;
    user_rb_t *goal_node = NULL;
    int res=0;

    while(node)
    {
        goal_node = rb_entry(node, user_rb_t, user_node);
        res = mac_cmp(umac, goal_node->umac);
        if(res<0)
            node = node->rb_left;
        else if(res>0)
            node = node->rb_right;
        else
            return goal_node;
    }

    return NULL;
}


//rb_insert
/*
描述:插入節點
返回:true or FLASE
*/
int user_rb_insert(struct rb_root *root, uint8_t *umac)
{
    struct rb_node **new = &(root->rb_node);
    struct rb_node *parent = NULL;
    user_rb_t *goal_node = NULL;
    int res=0;

    while(*new)
    {
        parent = *new;
        goal_node = rb_entry(*new, user_rb_t, user_node);
        res = mac_cmp(umac, goal_node->umac);
        if(res<0)
            new = &((*new)->rb_left);
        else if(res>0)
            new = &((*new)->rb_right);
        else
            return true;    
    }

    goal_node = create_user_node(umac);
    if(goal_node == NULL)
        return false;

    //add new node
    rb_link_node(&goal_node->user_node, parent, new);
    //rebalance rbtree
    rb_insert_color(&goal_node->user_node, root);

    return true;
}

/*
描述:刪除單個節點
*/
void user_rb_delete(struct rb_root *root, uint8_t *umac)
{
    user_rb_t *goal_node = user_rb_find(root, umac);
    if(goal_node != NULL)
    {
        rb_erase(&goal_node->user_node, root);
        kfree(goal_node);
    }
}

/*
描述:刪除整顆紅黑樹
*/
void user_rb_destory(struct rb_root *root)
{
    struct rb_node *node = NULL, *tmp_node = NULL;
    user_rb_t *goal_node = NULL;

    for(node = rb_first(root); node; )
    {

        tmp_node = rb_next(node);
        goal_node = rb_entry(node, user_rb_t, user_node);
        rb_erase(node, root); 
        kfree(goal_node);
        node = tmp_node;
    }
}
struct mytype *my_search(struct rb_root *root, char *string)
{
  struct rb_node *node = root->rb_node;
  while (node)
  {
    struct mytype *data = container_of(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 = container_of(*new, struct mytype, node);
    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 = mysearch(&mytree, "walrus");
if (data)
{
  rb_erase(&data->node, &mytree); //刪除節點,該函式內部呼叫____rb_erase_color()函式來對紅黑樹進行修正
  myfree(data);
}

遍歷紅黑樹

struct rb_node *node;
for (node = rb_first(&mytree); node; node = rb_next(node))
  printk("key=%s\n", rb_entry(node, struct mytype, node)->keystring);

相關推薦

linux核心運用例項

linux核心版本linux-3.10.36 在linux核心原始碼中,紅黑樹是一個比較獨立的模組,很容易將其剝離出來,拿到應用層使用。 結構 linux核心的rb_node結構體 struct rb_node { unsigned long

詳解Linux核心演算法的實現

    開發平臺:Ubuntu11.04     核心原始碼:linux-2.6.38.8.tar.bz2     平衡二叉樹(BalancedBinary Tree或Height-Balanced Tree)又稱AVL樹。它或者是一棵空樹,或者是具有下列性質的二叉樹:

根堆效能對比

因為nginx與libevent採用了不同的資料結構來維護超時事件,其中nginx採用了紅黑樹,libevent採用的是小根堆,所以一直比較好奇,這兩種資料結構誰在這種應用場景下更合適(當做優先權佇列來用) 好吧,好奇那就試一下就好了。。。 小根堆就用前面的那篇文章中自己實現的那個程式碼,程式碼比較挫,也沒

Linux 4 15核心TCP的重傳佇列變成

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

原理淺談(附Linux核心原始碼註釋)

引言:紅黑樹(英語:Red–black tree)是一種自平衡二叉查詢樹,是在電腦科學中用到的一種資料結構,典型的用途是實現關聯陣列。它是在1972年由魯道夫·貝爾發明的,他稱之為"對稱二叉B樹",它現代的名字是在Leo J. Guibas和Robert Sedgewick於19

真正理解,真正的(Linux核心裡大量用到的資料結構,且常被二貨問到)

作為一種資料結構,紅黑樹可謂不算樸素,因為各種宣傳讓它過於神祕,網上搜羅了一大堆的關於紅黑樹的文章,不外乎千篇一律,介紹概念,分析效能,貼上程式碼,然後給上罪惡的一句話,它最壞情況怎麼怎麼地...              我們想,一棵二叉樹怎麼就是最壞情況,那就是它退化為一

(三)之 Linux核心的經典實現

1 /* 2 Red Black Trees 3 (C) 1999 Andrea Arcangeli <[email protected]> 4 (C) 2002 David Woodhouse <[email protected

linux核心分析--核心中的資料結構之(續)

#include<linux/rbtree.h> #include <linux/string.h> #include "kn_common.h" MODULE_LICENSE("Dual BSD/GPL"); struct student { int id;

linux核心分析--核心中的資料結構之(四)

紅黑樹由於節點顏色的特性,保證其是一種自平衡的二叉搜尋樹。 紅黑樹的一系列規則雖然實現起來比較複雜,但是遵循起來卻比較簡單,而且紅黑樹的插入,刪除效能也還不錯。 所以紅黑樹在核心中的應用非常廣泛,掌握好紅黑樹,即有利於閱讀核心原始碼,也可以在自己的程式碼中借鑑這種資料結構。 紅黑樹必

vs 最

紅黑樹插入是最壞情況要比較2logN次(最高的高度)外加不超過兩次旋轉,最小堆最壞情況是logN次 紅黑樹刪除不需要比較只需要不超過3旋轉,查詢最小值需要遍歷logN,如果刪除最小值樹調整一般很小 最小堆查詢頂節點是O(1),而刪除頂節點在任何情況下都是個最壞的情況,需要比較2logN次 紅黑樹的最壞情況在旋

漫畫演算法:什麼是?(適合初學白簡單易懂)

———————————— 二叉查詢樹(BST)具備什麼特性呢? 1.左子樹上所有結點的值均小於或等於它的根結點的值。 2.右子樹上所有結點的值均大於或等於它的根結點的值。 3.左、右子樹也分別為二叉排序樹。 下

Linux虛擬記憶體區域管理中的應用

參考資料:http://wenku.baidu.com/view/f0795f8783d049649b66586f.html Linux核心中每一個使用者程序都可以訪問4GB的線性虛空間,為了能表達真正被程序使用的虛擬記憶體空間,Linux定義了虛擬儲存區域(virtua

堆/雜湊表/二叉/平衡二叉/的意義

接觸堆資料結構是在排序裡面講的,空間複雜度O(1),時間複雜度O(NlogN),但是在實踐中還是不如快速排序(好像快速排序可以更好的利用硬體特性)。堆 的意義就在於:最快的找到最大/最小值,在堆結構中插入一個值重新構造堆結構,取走最大/最下值後重新構造堆結構 其時間複雜度為O(logN),而其他方法最少為O

使用核心資料結構: rbtree

一、使用核心紅黑樹檔案rbtree 1.1 核心紅黑樹檔案         rbtree.h:/usr/src/kernels/2.6.32-279.el6.x86_64/include/linux/rbtree.h         rbtree.c:/usr/src/ke

【bzoj3227】

發現 blog ret amp 這樣的 spa 兩個 include log 神TM的紅黑樹,其實本質上應該還是一種樹dp的問題…… 一開始想了一個比較裸的樹dp,後來發現還有更強的做法。 每個前端黑節點是看作一個物品,然後這就是很典型的樹形dp的問題。 不過可以這麽考慮,

圖解集合7:概念、的插入及旋轉操作詳細解讀

集合 得到 2個 排序。 數據流 except boolean 修正 split 原文地址http://www.cnblogs.com/xrq730/p/6867924.html,轉載請註明出處,謝謝! 初識TreeMap 之前的文章講解了兩種Map,分別是HashMa

C++實現

con colors end ase 復制代碼 設置 typename ucc 技術 1 /* 2 * rbtree.h 3 * 1. 每個節點是紅色或者黑色 4 * 2. 根節點是黑色 5 * 3. 每個葉子節點是黑色(該葉子節點就空的節點)

數據結構學習筆記-排序/隊/棧/鏈/堆/查找/

算法 數據結構排序:插入排序:每次從剩余數據中選取一個最小的,插入已經排序完成的序列中合並排序:將數據分成左右兩組分別排序,然後合並,對每組數據的排序遞歸處理。冒泡排序:重復交換兩個相鄰元素,從a[1]開始向a[0]方向冒泡,然後a[2]...當a[i]無法繼續往前擠的時候說明前面的更小了,而且越往前越小(擠

查找(一)史上最簡單清晰的解說

ont 演示 detail align article 向上 節點 動態插入 列表 查找(一) 我們使用符號表這個詞來描寫敘述一張抽象的表格。我們會將信息(值)存儲在當中,然後依照指定的鍵來搜索並獲取這些信息。鍵和值的詳細意義取決於不同的應用。 符號表中可能會保

教你透徹了解

black ade 我們 工作 key 針對 otn strong lean 教你透徹了解紅黑樹 作者:July、saturnman 2010年12月29日 本文參考:Google、算法導論、STL源碼剖析、計算機程序設計藝術。 推薦閱讀: Left-