B樹的定義 插入和刪除

2021-07-04 19:30:07 字數 4790 閱讀 7997

b樹是為磁碟或其他直接訪問的輔助儲存裝置而設計的一種平衡搜尋樹。

一棵b樹是具有以下性質的有根樹:

1. 每個結點x有下面的屬性:

a. x.n,當前儲存在結點x中的關鍵字個數;

b. x.n個關鍵字本身,x.key[1], x.key[2], ..., x.key[x.n],以非降序存放,使得:

x.key[1]<=x.key[2]<=...<=x.key[x.n]

c. s.leaf 乙個布林值,如果x為葉結點則為true,如果為內部結點,則為false

2. 每個內部結點x還包含x.n+ 1個指向孩子結點的指標。葉結點沒有孩子,其孩子指標沒有意義。

3. 關鍵字x.key[i]對儲存在各子樹中的關鍵字的範圍加以分割 :如果k[i]為任意乙個儲存在以x.c[i]為根的子樹中的關鍵字,那麼

k1<=x.key[i]<=k2<=x.key[2]<=...<=x.key[x.n]<=k[x.n+1]

4. 每個孩子結點都具有相同的深度,即樹高h

5. 每個孩子結點的所包含的關鍵字的個數有上屆和下屆,用乙個被稱為b樹的最小度數t來固定表示。

a.  除了根結點以外的每個結點必須包含至少 t -  1 個關鍵字,因此,除了根結點以外,每個內部結點必須包含至少 t 個孩子

b. 每個結點至多可以包含 2t - 1個關鍵字,因此,每個內部結點至多可以包含 2t 個孩子。當乙個內部結點包含 2t-1個關鍵字的時候,我們就說這個結點是滿的。

在進行b樹的插入操作的時候,要防止插入的結點的關鍵字個數超過 2t - 1。當要插入乙個滿結點的時候,要進行**操作。

將整個滿結點**成各含有 t- 1 個結點的兩個結點,和中間的乙個關鍵字(不要忘記它的孩子)。

在演算法導論中是用單程演算法進行**操作的(單程演算法:從樹的根開始往下,沒有任何返回向上的操作)。

從根開始插入,將沿途遇到的所有的滿結點進行**,這樣就保證了插入的結點不是滿結點。

當根結點是滿結點的時候需要**根結點,並生成新的根。

bool bsubtree::insert(const keytype key)  else 

return false;

}

插入操作的輔助操作,當不是在根結點插入的時候,需要用這個輔助操作進行遞迴插入。

bool bsubtree::insert_notfull(bsubtreenodeptr pnode, const keytype key) 

pnode->_key[i + 1] = key;

++pnode->_n;

return true;

} else

// 執行這一步之後,pnode->_key[i - 1] <= key <= pnode->_key[i]

// key <= pnode->_key[i] <= pnode->_child[i + 1]->key[0]<=

// pnode->_child[i + 1]->_key[pnode->_child[i]->_n - 1] <= pnode->key[i + 1]

++i;

if (pnode->_maxchildnum - 1 == pnode->_child[i]->_n)

}return insert_notfull(pnode->_child[i], key);

}

b樹的**操作是將乙個滿結點的後半部分(t-1個關鍵字,t個孩子)直接剪貼到乙個新結點中,並中間結點(第t個關鍵字,從第乙個開始)上移到滿結點的父結點中。時間複雜度為o(n)。

bsubtreenodeptr rightchild = new bsubtreenode(pnode->_maxchildnum);

if (false == rightchild->init())

bsubtreenodeptr leftchild = pnode->_child[index];

unsigned int t = leftchild->_maxchildnum / 2;

rightchild->_isleaf = leftchild->_isleaf;

rightchild->_n = t - 1;

// **leftchild,把leftchild的後半部分複製到rightchild

for (unsigned int j = 0; j < t - 1; ++j)

if (!leftchild->_isleaf)

} leftchild->_n = t - 1;

// 把從index + 1開始的孩子一直往後挪,也就是大於pnode->key[index]的孩子往後挪

// 這時候pnode->_child[index + 2] = pnode->nodep[index+ 1]

for (unsigned int j = pnode->_n; j > index; --j)

pnode->_child[index + 1] = rightchild;

// 把從index開始的關鍵字往後挪,也就是大於pnode->key[index]的關鍵字往後挪

// 這時候pnode->_key[index + 1] = pnode->_key[index]

for (unsigned int j = pnode->_n - 1; j > index - 1; --j)

// 將中間關鍵字上移到父結點中。

pnode->_key[index] = leftchild->_key[t - 1];

++pnode->_n;

return true;

}

b樹的刪除操作比較複雜。

b樹的刪除包括以下三個情況:

1. 如果關鍵字k在葉節點x中,則從x中刪除;

2. 如果關鍵字k在內部結點x中,則:

a. 如果x的左兄弟y至少包含 t 個關鍵字,則找出以y為根的子樹中最大的關鍵字k1,遞迴的刪除k1,並用k1代替k

b.如果x的由兄弟z至少包含 t 個關鍵字,則找出以z為根的子樹中最小的關鍵字k1,遞迴的刪除k1,並用k1代替k

c. 否則就合併左右兄弟和關鍵字k到y中,這樣y結點中就含有了 2t - 1 個關鍵字,x也失去了指向z的孩子。刪除x中指向z的孩字,釋放z的記憶體,並遞迴的從y中刪除k。

3如果關鍵字k當前不在內部結點x中,則確定包含k的子樹的根x.c[i]。如果,x.c[i]的關鍵字個數為t - 1,那麼就要用下面兩個方法為x.c[i]補充乙個關鍵字:

a. 如果x.[i]只有 t - 1個關鍵字,但是它的左右兄弟至少包含t個關鍵字,則將x中的某個關鍵字下移到x.c[i]中,將x.c[i]的左右兄弟中的某個關鍵字上移到x中,相應的孩子指標也要移動。

b. 如果x.c[i]的左右兄弟都只有 t - 1個關鍵字,那麼就將x.c[i]與其中乙個兄弟合併在一起變成新的結點。將x的乙個關鍵字下移到新結點中,使下移的結點稱為新結點的中間關鍵字。

bool bsubtree::delete(bsubtreenodeptr pnode, const keytype key) 

} if (key == pnode->_key[i])

return true;

} else

pnode->_key[i] = p->_key[p->_n - 1];

return delete(p, p->_key[p->_n - 1]);

}else if (pnode->_child[i + 1]->_n > t -1)

pnode->_key[i + 1] = p->_key[0];

return delete(p ,p->_key[0]);

}else

pnode->_child[i]->_n += pnode->_child[i + 1]->_n + 1;

delete pnode->_child[i + 1];

for (index = i; index < pnode->_n - 1; ++index)

return delete(pnode->_child[i], key);}}

} else if (false == pnode->_isleaf) else

pnode->_child[i]->_child[1] = pnode->_child[i]->_child[0];

pnode->_child[i]->_key[0] = pnode->_key[i];

pnode->_child[i]->_child[0] = pnode->_child[i - 1]->_child[pnode->_child[i - 1]->_n];

++pnode->_child[i]->_n;

pnode->_key[i] = pnode->_child[i - 1]->_key[pnode->_child[i - 1]->_n];

--pnode->_child[i - 1]->_n;

}else if (pnode->_child[i + 1]->_n > t - 1)

pnode->_child[i + 1]->_child[pnode->_child[i + 1]->_n - 1] =

pnode->_child[i + 1]->_child[pnode->_child[i + 1]->_n];

--pnode->_child[i + 1]->_n;

}else

--pnode->_n;

return delete(pnode->_child[i], key);}}

} else

return true;

}

B樹插入刪除操作

b 樹定義 一種平衡的多路查詢樹。用於 索引組織檔案,減少訪問外存次數,節約搜尋時間。一棵m階b 樹或為空樹,或滿足下列特性 為盡量簡單,把考試不考的內容全部略去 1 樹中每個結點至多有m個分支,最少有 m 2 分支,取上整,除根結點外 2.關鍵字數大於等於m 2 1,小於等於m 1,2取上整 3 ...

B樹(又稱B 樹)插入 刪除操作

b樹是一種平衡的多分樹,通常我們說m階的b樹,它必須滿足如下條件 1 每個結點至多有m個子結點 2 除根結點和葉結點外,其它每個結點至少有ceil m 2 個子結點 3 根結點至少有兩個子結點 唯一例外的是根結點就是葉子結點 4 所有的葉結點在同一層 5 有k個子結點的非根結點恰好包含k 1個關鍵碼...

B 樹的插入 刪除操作

include include define maxm 10 b 樹最大階數 typedef int keytype keytype是關鍵字型別 typedef struct node btnode typedef struct b 樹的查詢結果型別 result int m m階b 樹作為全域性變...