青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

那誰的技術(shù)博客

感興趣領(lǐng)域:高性能服務(wù)器編程,存儲,算法,Linux內(nèi)核
隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
數(shù)據(jù)加載中……

Btree算法實(shí)現(xiàn)代碼

基于<<算法導(dǎo)論>>中關(guān)于btree算法的描述,雖然書中沒有關(guān)于刪除結(jié)點(diǎn)算法的偽碼實(shí)現(xiàn),不過還是根據(jù)描述寫了出來,經(jīng)過測試,似乎是沒有問題,歡迎測試找bug.

不過,值得一提的是,btree算法大部分情況下是使用在操作存放在諸如磁盤等慢速且大容量介質(zhì)中的,但是這里給出的算法仍然是操作的內(nèi)存中的數(shù)據(jù).如何使用這個算法操作存放在磁盤的數(shù)據(jù),恐怕還要自定義文件的格式等,我對這方面還沒有涉及到,以后會抽空研究如tokyocabinet等數(shù)據(jù)庫的代碼,給出一個解決方案來,如果能做到這一點(diǎn),基本上就可以算是一個小型的數(shù)據(jù)庫的后端存儲系統(tǒng)了.

話說回來,這份代碼我編碼調(diào)試了很久,幾百行的代碼從國慶在家休息的時候開始,前后花費(fèi)了將近一周時間.我想,諸如紅黑樹/btree這樣的復(fù)雜數(shù)據(jù)結(jié)構(gòu)的算法之所以難以調(diào)試,很大的原因在于,即使在某一處你不小心犯了一個錯誤,程序運(yùn)行時也可能不是在這個地方core dump,因?yàn)槟闫茐牧诉@個結(jié)構(gòu)而只在后面才反映出來,于是,加大了調(diào)試的難度.所以,這就需要自己多閱讀資料,加深對算法的理解,盡可能的肉眼多審核幾次代碼.

我之前研究過紅黑樹,研究過memcached,自己也寫了一個commoncache,看來,我個人更感興趣的方向是這種大規(guī)模數(shù)據(jù)的處理上,很有挑戰(zhàn)的說.未來,將繼續(xù)在這方面發(fā)力,希望能有機(jī)會從事這方面的工作,如Linux文件系統(tǒng),分布式文件系統(tǒng),云計算等等方向.

頭文件:
/*
 * implementation of btree algorithm, base on <<Introduction to algorithm>>
 * author: lichuang
 * blog: m.shnenglu.com/converse
 
*/

#ifndef __BTREE_H__
#define __BTREE_H__

#define M 4 
#define KEY_NUM (2 * M - 1)

typedef 
int type_t;

typedef 
struct btree_t
{
    
int num;                        /* number of keys */
    
char leaf;                      /* if or not is a leaf */
    type_t key[KEY_NUM];
    
struct btree_t* child[KEY_NUM + 1];
}btree_t, btnode_t;

btree_t
*    btree_create();
btree_t
*    btree_insert(btree_t *btree, type_t key);
btree_t
*    btree_delete(btree_t *btree, type_t key);

/*
 * search the key in the btree, save the key index of the btree node in the index
 
*/
btree_t
*    btree_search(btree_t *btree, type_t key, int *index);

#endif /* __BTREE_H__ */


實(shí)現(xiàn)代碼以及測試文件:
/*
 * implementation of btree algorithm, base on <<Introduction to algorithm>>
 * author: lichuang
 * blog: m.shnenglu.com/converse
 
*/

#include 
"btree.h"
#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>

static btree_t* btree_insert_nonfull(btree_t *btree, type_t key);
static btree_t* btree_split_child(btree_t *parent, int pos, btree_t *child);
static int      btree_find_index(btree_t *btree, type_t key, int *ret);

btree_t
* btree_create()
{
    btree_t 
*btree;

    
if (!(btree = (btree_t*)malloc(sizeof(btree_t))))
    {
        printf(
"[%d]malloc error!\n", __LINE__);
        
return NULL;
    }

    btree
->num = 0;
    btree
->leaf = 1;

    
return btree;
}

btree_t
* btree_insert(btree_t *btree, type_t key)
{
    
if (btree->num == KEY_NUM)
    {
        
/* if the btree is full */
        btree_t 
*p;
        
if (!(p = (btree_t*)malloc(sizeof(btree_t))))
        {
            printf(
"[%d]malloc error!\n", __LINE__);
            
return NULL;
        }
        p
->num = 0;
        p
->child[0= btree;
        p
->leaf = 0;
        btree 
= btree_split_child(p, 0, btree);
    }

    
return btree_insert_nonfull(btree, key);
}

btree_t
* btree_delete(btree_t *btree, type_t key)
{
    
int index, ret, i;
    btree_t 
*preceding, *successor;
    btree_t 
*child, *sibling;
    type_t replace;

    index 
= btree_find_index(btree, key, &ret);

    
if (btree->leaf && !ret)
    {
        
/* 
           case 1:
           if found the key and the node is a leaf then delete it directly 
        
*/
        memmove(
&btree->key[index], &btree->key[index + 1], sizeof(type_t) * (btree->num - index - 1));
        
--btree->num;
        
return btree;
    }
    
else if (btree->leaf && ret)
    {
        
/* not found */
        
return btree;
    }

    
if (!ret)               /* btree includes key */
    {
        
/* 
           case 2:
           If the key k is in node x and x is an internal node, do the following:
         
*/
        preceding 
= btree->child[index];
        successor 
= btree->child[index + 1];

        
if (preceding->num >= M) /* case 2a */
        {
            
/*
               case 2a:
               If the child y that precedes k in node x has at least t keys, 
               then find the predecessor k′ of k in the subtree rooted at y. 
               Recursively delete k′, and replace k by k′ in x. 
               (Finding k′ and deleting it can be performed in a single downward pass.)
             
*/
            replace 
= preceding->key[preceding->num - 1];
            btree
->child[index] = btree_delete(preceding, replace);
            btree
->key[index] = replace;
            
return btree;
        }
        
if (successor->num >= M)  /* case 2b */
        {
            
/*
               case 2b:
               Symmetrically, if the child z that follows k in node x 
               has at least t keys, then find the successor k′ of k 
               in the subtree rooted at z. Recursively delete k′, and 
               replace k by k′ in x. (Finding k′ and deleting it can 
               be performed in a single downward pass.)
             
*/
            replace 
= successor->key[0];
            btree
->child[index + 1= btree_delete(successor, replace);
            btree
->key[index] = replace;
            
return btree;
        }
        
if ((preceding->num == M - 1&& (successor->num == M - 1)) /* case 2c */
        {
            
/*
               case 2c:
               Otherwise, if both y and z have only t - 1 keys, merge k
               and all of z into y, so that x loses both k and the pointer 
               to z, and y now contains 2t - 1 keys. Then, free z and 
               recursively delete k from y.
             
*/
            
/* merge key and successor into preceding */
            preceding
->key[preceding->num++= key;
            memmove(
&preceding->key[preceding->num], &successor->key[0], sizeof(type_t) * (successor->num));
            memmove(
&preceding->child[preceding->num], &successor->child[0], sizeof(btree_t** (successor->num + 1));
            preceding
->num += successor->num;

            
/* delete key from btree */
            
if (btree->num - 1 > 0)
            {
                memmove(
&btree->key[index], &btree->key[index + 1], sizeof(type_t) * (btree->num - index - 1));
                memmove(
&btree->child[index + 1], &btree->child[index + 2], sizeof(btree_t** (btree->num - index - 1));
                
--btree->num;
            }
            
else
            {
                
/* if the parent node contain no more child, free it */
                free(btree);
                btree 
= preceding;
            }

            
/* free successor */
            free(successor);

            
/* delete key from preceding */
            btree_delete(preceding, key);

            
return btree;
        }
    }

    
/* btree not includes key */
    
if ((child = btree->child[index]) && child->num == M - 1)
    {
        
/*
           case 3:
           If the key k is not present in internal node x, determine 
           the root ci[x] of the appropriate subtree that must contain k, 
           if k is in the tree at all. If ci[x] has only t - 1 keys, 
           execute step 3a or 3b as necessary to guarantee that we descend 
           to a node containing at least t keys. Then, finish by recursing 
           on the appropriate child of x. 
         
*/
        
/* 
           case 3a:
           If ci[x] has only t - 1 keys but has an immediate sibling 
           with at least t keys, give ci[x] an extra key by moving a 
           key from x down into ci[x], moving a key from ci[x]'s immediate 
           left or right sibling up into x, and moving the appropriate 
           child pointer from the sibling into ci[x].
         
*/
        
if ((index < btree->num) && 
                (sibling 
= btree->child[index + 1]) &&
                (sibling
->num >= M))
        {
            
/* the right sibling has at least M keys */
            child
->key[child->num++= btree->key[index];
            btree
->key[index]        = sibling->key[0];

            child
->child[child->num] = sibling->child[0];

            sibling
->num--;
            memmove(
&sibling->key[0], &sibling->key[1], sizeof(type_t** (sibling->num));
            memmove(
&sibling->child[0], &sibling->child[1], sizeof(btree_t** (sibling->num + 1));
        }
        
else if ((index > 0&& 
                (sibling 
= btree->child[index - 1]) &&
                (sibling
->num >= M))
        {
            
/* the left sibling has at least M keys */
            memmove(
&child->key[1], &child->key[0], sizeof(type_t) * child->num);
            memmove(
&child->child[1], &child->child[0], sizeof(btree_t** (child->num + 1));
            child
->key[0= btree->key[index - 1];
            btree
->key[index - 1]  = sibling->key[sibling->num - 1];
            child
->child[0= sibling->child[sibling->num];

            child
->num++;
            sibling
->num--;
        }
        
/* 
           case 3b:
           If ci[x] and both of ci[x]'s immediate siblings have t - 1 keys, 
           merge ci[x] with one sibling, which involves moving a key from x 
           down into the new merged node to become the median key for that node.
         
*/
        
else if ((index < btree->num) && 
                (sibling 
= btree->child[index + 1]) &&
                (sibling
->num == M - 1))
        {
            
/* 
               the child and its right sibling both have M - 1 keys,
               so merge child with its right sibling
             
*/
            child
->key[child->num++= btree->key[index];
            memmove(
&child->key[child->num], &sibling->key[0], sizeof(type_t) * sibling->num);
            memmove(
&child->child[child->num], &sibling->child[0], sizeof(btree_t** (sibling->num + 1));
            child
->num += sibling->num;

            
if (btree->num - 1 > 0)
            {
                memmove(
&btree->key[index], &btree->key[index + 1], sizeof(type_t) * (btree->num - index - 1));
                memmove(
&btree->child[index + 1], &btree->child[index + 2], sizeof(btree_t** (btree->num - index - 1));
                btree
->num--;
            }
            
else
            {
                free(btree);
                btree 
= child;
            }

            free(sibling);
        }
        
else if ((index > 0&& 
                (sibling 
= btree->child[index - 1]) &&
                (sibling
->num == M - 1))
        {
            
/* 
               the child and its left sibling both have M - 1 keys,
               so merge child with its left sibling
             
*/
            sibling
->key[sibling->num++= btree->key[index - 1];
            memmove(
&sibling->key[sibling->num], &child->key[0], sizeof(type_t) * child->num);
            memmove(
&sibling->child[sibling->num], &child->child[0], sizeof(btree_t** (child->num + 1));
            sibling
->num += child->num;

            
if (btree->num - 1 > 0)
            {
                memmove(
&btree->key[index - 1], &btree->key[index], sizeof(type_t) * (btree->num - index));
                memmove(
&btree->child[index], &btree->child[index + 1], sizeof(btree_t** (btree->num - index));
                btree
->num--;
            }
            
else
            {
                free(btree);
                btree 
= sibling;
            }

            free(child);

            child 
= sibling;
        }
    }

    btree_delete(child, key);
    
return btree;
}

btree_t
* btree_search(btree_t *btree, type_t key, int *index)
{
    
int i;

    
*index = -1;

    
for (i = 0; i < btree->num && key > btree->key[i]; ++i)
        ;

    
if (i < btree->num && key == btree->key[i])
    {
        
*index = i;
        
return btree;
    }

    
if (btree->leaf)
    {
        
return NULL;
    }
    
else
    {
        
return btree_search(btree->child[i], key, index);
    }
}

/*
 * child is the posth child of parent
 
*/
btree_t
* btree_split_child(btree_t *parent, int pos, btree_t *child)
{
    btree_t 
*z;
    
int i;

    
if (!(z = (btree_t*)malloc(sizeof(btree_t))))
    {
        printf(
"[%d]malloc error!\n", __LINE__);
        
return NULL;
    }

    z
->leaf = child->leaf;
    z
->num = M - 1;
    
    
/* copy the last M keys of child into z */
    
for (i = 0; i < M - 1++i)
    {
       z
->key[i] = child->key[i + M];
    }

    
if (!child->leaf)
    {
        
/* copy the last M children of child into z */
        
for (i = 0; i < M; ++i)
        {
            z
->child[i] = child->child[i + M];
        }
    }
    child
->num = M - 1;

    
for (i = parent->num; i > pos; --i)
    {
        parent
->child[i + 1= parent->child[i];
    }
    parent
->child[pos + 1= z;

    
for (i = parent->num - 1; i >= pos; --i)
    {
        parent
->key[i + 1= parent->key[i];
    }
    parent
->key[pos] = child->key[M - 1];

    parent
->num++;

    
return parent;
}

int btree_find_index(btree_t *btree, type_t key, int *ret)
{
    
int i, num;

    
for (i = 0, num = btree->num; i < num && (*ret = btree->key[i] - key) < 0++i)
        ;
    
/*
     * when out of the loop, three conditions may happens:
     * ret == 0 means find the key,
     * or ret > 0 && i < num means not find the key,
     * or ret < 0 && i == num means not find the key and out of the key array range
     
*/

    
return i;
}

/*
 * btree is not full  
 
*/
btree_t
* btree_insert_nonfull(btree_t *btree, type_t key)
{
    
int i;

    i 
= btree->num - 1;

    
if (btree->leaf)
    {
        
/* find the position to insert the key */
        
while (i >= 0 && key < btree->key[i])
        {
            btree
->key[i + 1= btree->key[i];
            
--i;
        }

        btree
->key[i + 1= key;

        btree
->num++;
    }
    
else
    {
        
/* find the child to insert the key */
        
while (i >= 0 && key < btree->key[i])
        {
            
--i;
        }

        
++i;
        
if (btree->child[i]->num == KEY_NUM)
        {
            
/* if the child is full, then split it */
            btree_split_child(btree, i, btree
->child[i]);
            
if (key > btree->key[i])
            {
                
++i;
            }
        }

        btree_insert_nonfull(btree
->child[i], key);
    }

    
return btree;
}

#define NUM 20000

int main()
{
    btree_t 
*btree;
    btnode_t 
*node;
    
int index, i;

    
if (!(btree = btree_create()))
    {
        exit(
-1);
    }

    
for (i = 1; i < NUM; ++i)
    {
        btree 
= btree_insert(btree, i);
    }

    
for (i = 1; i < NUM; ++i)
    {
        node 
= btree_search(btree, i, &index);

        
if (!node || index == -1)
        {
            printf(
"insert error!\n");
            
return -1;
        }
    }

    
for (i = 1; i < NUM; ++i)
    {
        btree 
= btree_delete(btree, i);

        btree 
= btree_insert(btree, i);
    }

    
return 0;
}


posted on 2009-10-13 21:00 那誰 閱讀(11619) 評論(8)  編輯 收藏 引用 所屬分類: 算法與數(shù)據(jù)結(jié)構(gòu)

評論

# re: Btree算法實(shí)現(xiàn)代碼[未登錄]  回復(fù)  更多評論   

b-tree..只有膜拜的份啊
2009-10-13 21:55 | vincent

# re: Btree算法實(shí)現(xiàn)代碼  回復(fù)  更多評論   

good job!! recently, referring to mit's introduction to algorithms. just for basic.
2009-10-13 21:57 | tiny

# re: Btree算法實(shí)現(xiàn)代碼[未登錄]  回復(fù)  更多評論   

sqlite也實(shí)現(xiàn)了一個btree,自己的文件格式,緩存
2009-10-13 23:10 | true

# re: Btree算法實(shí)現(xiàn)代碼  回復(fù)  更多評論   

C語言風(fēng)格。。
2009-10-15 09:02 | expter

# re: Btree算法實(shí)現(xiàn)代碼  回復(fù)  更多評論   

@true
怎么用呢?》
2010-11-20 22:34 | 在以

# re: Btree算法實(shí)現(xiàn)代碼  回復(fù)  更多評論   

我將 main中
btree_delete調(diào)用那塊修改為隨機(jī)刪除key
z = rand() % NUM;
btree = btree_delete(btree, z);

并且在btree_delete中加了判斷
if (btree == NULL || btree->num == 0) { return btree; }

為何會出現(xiàn)段錯誤?
用valgrind查看
/* btree not includes key */
if ((child = btree->child[index]) && child->num == M - 1)
這里報 Invalid read of size 4
這是為何 請指教

2011-10-26 17:10 | 郭凱

# re: Btree算法實(shí)現(xiàn)代碼  回復(fù)  更多評論   

貌似發(fā)現(xiàn)錯誤了
case 3a 中
memmove(&sibling->key[0], &sibling->key[1], sizeof(type_t*) * (sibling->num));
"type_t*" 改為 "type_t" 就OK了
2011-10-27 01:53 | 郭凱

# re: Btree算法實(shí)現(xiàn)代碼[未登錄]  回復(fù)  更多評論   

可以實(shí)現(xiàn)動態(tài)確定btree子樹的算法嗎?
2013-01-16 14:14 | eric
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲欧美三级在线| 一本色道久久综合狠狠躁篇怎么玩 | 欧美激情日韩| 久久国产精品99国产精| 夜夜爽99久久国产综合精品女不卡| 亚洲福利一区| 最新国产乱人伦偷精品免费网站| 亚洲精品乱码久久久久| 日韩亚洲精品电影| 亚洲理论电影网| 一区二区三区久久精品| 欧美亚洲免费| 蜜臀久久久99精品久久久久久| 亚洲福利视频网站| 亚洲精品乱码久久久久久久久| 亚洲精品123区| 亚洲性av在线| 久久久久久久尹人综合网亚洲| 巨乳诱惑日韩免费av| 欧美粗暴jizz性欧美20| 国产精品久久国产三级国电话系列 | 亚洲精品国精品久久99热| 亚洲精品视频在线看| 午夜在线视频观看日韩17c| 久久精品国产久精国产爱| 免费不卡在线观看av| 亚洲精品自在在线观看| 午夜在线观看免费一区| 欧美成人免费播放| 国产日韩欧美在线看| 亚洲精品小视频在线观看| 欧美一级黄色网| 美女精品网站| 国产欧美日本| 在线视频日韩| 欧美电影资源| 亚洲欧美日韩国产中文| 欧美精品久久一区二区| 在线观看福利一区| 午夜精品视频网站| 亚洲精品看片| 噜噜噜91成人网| 国产字幕视频一区二区| 亚洲欧美日韩成人| 亚洲精品中文字幕在线| 久久一本综合频道| 狠狠狠色丁香婷婷综合久久五月 | 久久先锋影音| 欧美一区二区三区日韩视频| 欧美日本簧片| 99精品欧美一区二区三区综合在线| 久久夜色精品国产噜噜av| 亚洲视频欧美在线| 亚洲美女尤物影院| 美国十次成人| 久久精品人人做人人爽电影蜜月| 欧美亚州韩日在线看免费版国语版| 亚洲激情电影在线| 欧美国产精品专区| 久久久精品一区| 在线观看欧美亚洲| 美女图片一区二区| 久久久久在线观看| 亚洲电影免费在线| 欧美激情综合色| 蜜桃av一区二区| 亚洲人成网站在线播| 亚洲高清av在线| 欧美精品日韩一区| 在线亚洲欧美视频| 亚洲视频一起| 国产综合久久久久久| 久久一区视频| 欧美福利一区二区三区| 一级成人国产| 亚洲男人的天堂在线| 国产一区视频在线观看免费| 女生裸体视频一区二区三区| 欧美成人午夜激情| 亚洲尤物视频网| 亚洲欧美中文日韩在线| 激情一区二区三区| 亚洲国产精品精华液2区45| 欧美日韩精品一区二区三区| 西西裸体人体做爰大胆久久久| 性伦欧美刺激片在线观看| 亚洲第一区在线观看| 日韩视频―中文字幕| 国内精品久久久久影院 日本资源| 久久野战av| 欧美日韩在线三区| 久久综合伊人77777尤物| 欧美日韩一区二| 久久久久国产一区二区三区| 欧美精品九九| 久久久久久久久久久成人| 欧美精品日韩综合在线| 久久精品视频免费播放| 欧美日本国产精品| 老色鬼精品视频在线观看播放| 欧美人成在线视频| 久久久噜噜噜久久久| 欧美日韩国产欧| 久久成人久久爱| 欧美日韩精选| 免费视频一区| 国产欧美一区二区色老头| 亚洲电影中文字幕| 国产亚洲激情| 日韩一级二级三级| 影音先锋久久| 午夜精品一区二区三区在线播放 | 欧美一级成年大片在线观看| 久久久精品国产免大香伊| 一区二区三区四区国产精品| 香港成人在线视频| 亚洲少妇最新在线视频| 久久亚洲私人国产精品va媚药| 亚洲一区欧美二区| 欧美日韩国产91| 亚洲国产高清高潮精品美女| 国产综合久久久久影院| 亚洲欧美日韩天堂一区二区| 日韩亚洲欧美一区二区三区| 久久综合电影| 久久婷婷人人澡人人喊人人爽| 国产精品久久久久77777| 亚洲欧洲在线播放| 亚洲精品国久久99热| 免费欧美高清视频| 免播放器亚洲| 亚洲黄色在线观看| 久久婷婷麻豆| 欧美丰满高潮xxxx喷水动漫| 尤物在线精品| 久久裸体艺术| 欧美成人午夜视频| 亚洲经典三级| 欧美精品18+| 亚洲黄色在线观看| 亚洲精品在线电影| 欧美人在线观看| av成人免费在线| 亚洲综合色视频| 国产精品久久7| 亚洲免费在线观看| 久久久99免费视频| 伊人成年综合电影网| 久久伊人精品天天| 欧美激情视频一区二区三区免费| 亚洲福利在线观看| 欧美日韩国产色综合一二三四| 日韩午夜av| 午夜欧美精品久久久久久久| 国产一本一道久久香蕉| 久久久久国产精品一区二区| 欧美成人a视频| 99v久久综合狠狠综合久久| 欧美日韩一区在线视频| 亚洲一级二级| 久热这里只精品99re8久| 亚洲国产日韩在线| 欧美视频三区在线播放| 欧美一区二区在线免费播放| 免费日韩精品中文字幕视频在线| 最新国产成人在线观看| 欧美色区777第一页| 久久精品国产亚洲高清剧情介绍| 久久久久综合| 亚洲午夜av在线| 国产亚洲一区二区精品| 久热精品视频在线观看一区| 日韩一级片网址| 久久精品视频在线观看| 99在线精品免费视频九九视| 国产日韩欧美中文| 欧美黄色小视频| 欧美专区日韩视频| 亚洲最黄网站| 欧美激情在线播放| 欧美在线视频免费观看| 一区二区三区视频在线看| 性久久久久久久久| 在线播放一区| 国产精品免费电影| 麻豆精品视频在线观看| 亚洲视频二区| 亚洲区一区二区三区| 久久久精品日韩| 亚洲欧美久久| 亚洲最新中文字幕| 亚洲福利在线观看| 黑人操亚洲美女惩罚| 欧美日韩一区在线观看| 久久综合精品一区| 性xx色xx综合久久久xx| 亚洲视频在线一区观看| 亚洲精品网站在线播放gif| 女同一区二区| 久久这里有精品视频|