b樹插入關鍵字
b樹插入是指插入到乙個已知的葉節點上,因為不能把關鍵字插入到乙個滿的葉結點上,故引入乙個操作,將乙個滿的結點y(有2t – 1個關鍵字)按其中間關鍵字key[y]**成兩個各含t – 1個關鍵字的節點,中間關鍵字提公升到y的雙親結點,如果y的雙親也是滿的,則自底向上傳播**。
如同二叉查詢樹,插入時,需要從根部沿著樹下降到葉子,當沿著樹往下查詢新關鍵字所屬位置時,就**遇到的每乙個滿結點,這樣就能保證,要**乙個滿結點y時,就能確保它的雙親不是滿的。
**圖示:
插入結點偽**:
b-tree-insert(t, k)作用是對b樹用單程下行遍歷方式插入關鍵字。3~9行處理根結點r為滿的情況。
b-tree-split-child(x, i, y) 第1~8行行建立乙個新結點,並將y的t – 1個最大關鍵字以及相應的t個子女給它,第九行調整關鍵字計數。第10~16行將z插入為x的乙個孩子,提公升y的中間關鍵字到x來**y和z,並調整x的關鍵字計數。
b-tree-insert-nonfull(x, k) 第3~8行處理x是葉子的情況,將關鍵字k插入x;如果不是,則第9~11確定向x的哪個子結點遞迴下降。第13行檢查遞迴是否將降至乙個滿子結點上,若是,14行用b-tree-split-child將該子結點分類成兩個非滿的孩子,第15~16行確定向兩個孩子中的哪乙個下降是正確的。
各種情況都包含的插入圖示:(最小度數t為3)
3)刪除操作:
書上沒有給出偽**,只給出了基本思路,設關鍵字為k,x為節點
1) 若k在x中,且x是葉節點,則從x中刪除k
2) 若k在x中,且x是內節點,則
a) 若x中前於k的子節點y包含至少t個關鍵字,則找出k在以y為根的子樹中的前驅k』。遞迴地刪除k』,並在x中用k』取代k。
b) 若x中後於k的子節點z包含至少t個關鍵字,則找出k在以z為根的子樹中的後繼k』。遞迴地刪除k』,並在x中用k』取代k。
c) 否則,將k和z所有關鍵字合併進y,然後,釋放z並將k從y中遞迴刪除。
3) 若k不在x中,則確定必包含k的正確的子樹的根ci[x]。若ci[x]只有t – 1個關鍵字,則執行a或b操作。然後,對合適的子節點遞迴刪除k。
a) 若ci[x]只包含t-1個關鍵字,但它的相鄰兄弟包含至少t個關鍵字,則將x中的某乙個關鍵字降至ci[x],將ci[x]的相鄰兄弟中的某乙個關鍵字公升至x,將該兄弟中合適的子女指標遷移到ci[x]中。
b) 若ci[x]與其所有相鄰兄弟節點都包含t-1個關鍵字,則將ci[x]與乙個兄弟合併,將x的乙個關鍵字移至新合併的節點。
刪除結點圖示:(最小度數為2)
完整實現**:
按關鍵字的順序遍歷b-樹:
(3, 11)
(7, 16)
(12, 4)
(24, 1)
(26, 13)
(30, 12)
(37, 5)
(45, 2)
(50, 6)
(53, 3)
(61, 7)
(70, 10)
(85, 14)
(90, 8)
(100, 9)
請輸入待查詢記錄的關鍵字: 26
(26, 13)
沒找到(37, 5)
#include
#include
#include
#include
using namespace std;
#define m 3 // b樹的階,暫設為3
//3階的b-數上所有非終點結點至多可以有兩個關鍵字
#define n 16 // 資料元素個數
#define max 5 // 字串最大長度 + 1
//記錄型別
struct recordnode[m + 1]; // key, recptr的0號單元未用
typedef btreenode bt;
typedef btreenode * position;
typedef btreenode * searchtree;
//b-樹查詢結果的型別
typedef struct result;
inline void print(bt c, int i) else else else , , , ,
, , , ,
, , , ,
, , , };
searchtree tree = null;//初始化一棵空樹
result res;//存放結果
int i;
for(i = 0; i < n; i++ ) else {
printf("沒找到\n");
puts("");
destroysearchtree(tree);
b+-tree:是應檔案系統所需而產生的一種b-tree的變形樹。
一棵m階的b+樹和m階的b樹的差異在於:
1.有n棵子樹的結點中含有n個關鍵字;(而b 樹是n棵子樹有n-1個關鍵字)
2.所有的葉子結點中包含了全部關鍵字的資訊,及指向含有這些關鍵字記錄的指標,且葉子結點本身依關鍵字的大小自小而大的順序鏈結。(而b 樹的葉子節點並沒有包括全部需要查詢的資訊)
3.所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。(而b 樹的非終節點也包含需要查詢的有效資訊)
a) 為什麼說b+-tree比b 樹更適合實際應用中作業系統的檔案索引和資料庫索引?
1) b+-tree的磁碟讀寫代價更低
b+-tree的內部結點並沒有指向關鍵字具體資訊的指標。因此其內部結點相對b 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入記憶體中的需要查詢的關鍵字也就越多。相對來說io讀寫次數也就降低了。
舉個例子,假設磁碟中的乙個盤塊容納16bytes,而乙個關鍵字2bytes,乙個關鍵字具體資訊指標2bytes。一棵9階b-tree(乙個結點最多8個關鍵字)的內部結點需要2個盤快。而b+樹內部結點只需要1個盤快。當需要把內部結點讀入記憶體中的時候,b 樹就比b+樹多一次盤塊查詢時間(在磁碟中就是碟片旋轉的時間)。
2) b+-tree的查詢效率更加穩定
由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每乙個資料的查詢效率相當。
5.b*-tree
b*-tree是b+-tree的變體,在b+樹非根和非葉子結點再增加指向兄弟的指標;b*樹定義了非葉子結點關鍵字個數至少為(2/3)*m,即塊的最低使用率為2/3(代替b+樹的1/2)。給出了乙個簡單例項,如下圖所示:
b+樹的**:當乙個結點滿時,分配乙個新的結點,並將原結點中1/2的資料複製到新結點,最後在父結點中增加新結點的指標;b+樹的**只影響原結點和父結點,而不會影響兄弟結點,所以它不需要指向兄弟的指標。
b*樹的**:當乙個結點滿時,如果它的下乙個兄弟結點未滿,那麼將一部分資料移到兄弟結點中,再在原結點插入關鍵字,最後修改父結點中兄弟結點的關鍵字(因為兄弟結點的關鍵字範圍改變了);如果兄弟也滿了,則在原結點與兄弟結點之間增加新結點,並各複製1/3的資料到新結點,最後在父結點增加新結點的指標。
所以,b*樹分配新結點的概率比b+樹要低,空間使用率更高;
二,b+樹
R資料結構
r語言可能大家不是很熟知,但r語言絕對是作圖建模最好用的語言。今天來給大家說說他的資料結構,先上圖 向量是儲存數值型 字元型或邏輯型資料的一種陣列 v v1 v2 print v 2 print v1 c 2,3 print v2 2 5 向量只能儲存同一種型別的資料,v2的資料型別看起來輸入不同,...
R資料結構
subject name c jonh jane doe steve 字元型向量 temperature c 98.1,98.6,101.4 浮點型向量 temperature 2 3 1 98.6 101.4 temperature 2 負號可以把該項排除在外 1 98.1 101.4 tempe...
資料結構課程大總結
o 資料結構包括邏輯結構 儲存結構 資料運算。其中,資料的邏輯結構又分為線性結構和非線性結構 資料的儲存結構分為順序結構 鏈式結構 索引結構 雜湊結構 資料運算分為插入運算 刪除運算 修改運算 查詢運算和排序運算。這後面所學的知識點都是以這為基礎的 舉個例子,後面所學的棧 佇列 陣列 樹 圖等等,儲...