B數,B+樹
阿新 • • 發佈:2018-03-18
int 不能 一個 數據 內存 過大 深度 平衡 OS
0 為什麽會有多叉樹
當在程序中存儲數據的時候,可以使用二叉搜索樹。
當輸入的過於均勻的時候可能生成深度過大的二叉搜索樹,最壞的情況是,輸入節點的key按照大小排序,此時生成的二叉搜索樹就是一個鏈表了。
因此,為了避免這種情況的出現,可以使用平衡二叉樹,例如AVL和紅黑樹。
但二叉搜索樹只是適用於數據存儲在內存中的情況。
當數據量過大,不能完全的在內存中存儲時,就需要將數據存儲到磁盤上。
為了檢索方便,仍然使用樹的結構。
如果存放在磁盤中的數據,仍然采用二叉搜索樹的形式,當磁盤中讀取出一塊數據,根據key的值,判斷目標應該在左子樹中,然後磁盤再去讀取左子樹數據所在磁盤位置的數據。然後叠代這個過程,直到找到了目標數據。
但是,磁盤每次讀取數據都需要一定的時間。因此樹高越大,那麽平均讀取依次數據需要讀取的磁盤次數也就越多。
cpu的計算速度遠快與磁盤讀取的次數,因此應該減少樹高,降低磁盤的讀取次數。
所以在每個節點中除了本節點key對應的值,再存儲多個子樹。而不是像二叉搜索樹,只存放左右子節點。
此時該結構就是B樹
2 B樹
2.1 結構
B樹的每個節點存放:
- 一個數值n,表示該節點中存在的節點個數。
- n個節點本身,按照節點關鍵字非降序存放(也就是從小打到),這n個節點的關鍵字,分割了本節點的n個子樹中key的取值範圍。
- 一個布爾值,表示概述是否是一個葉節點
- n+1個指針指向每一個子樹,取值範圍被n個關鍵字分割
註意:父節點的指針在子樹中的指向。
2.2 特點
B樹具有
- 每個葉節點的樹高相同
- 每個節點所包含關鍵字個數有上下界。稱為B樹的最小度數。用t表示,一個大節點中小節點的個數最少為t-1個,最多為2t-1,其子樹數量最多為2t個。因此當t=2時,為2-3-4樹。t越大,樹高越小
- B樹的根至少包含一個子樹,其他節點至少有t個子樹
2.3 搜索
B樹的根節點時鐘在主存中。
搜索過程:
Node *serch(Node *root,int k) { int i=0; for(;i<=root.n,k>x.key[i],++i) { } if(k==x.key[i]) { return x.child[i]; }else if(x.leaf == true) { return nullptr; }else{ return serch(read(x.key),k); } }
2.4 插入
B樹的插入,B樹的插入仍然和二叉樹的插入步驟類似,也就是說都要先判斷插入位置。
但是多了一個判斷:那麽就是一個節點中可存儲的節點個數,不能超過2t。當超過2t個的時候,需要這樣做。
- 遍歷找到要插入的位置。
- 判斷大節點中小節點的個數,如果為2t。那麽用本大節點中的中間節點將小結一分為二,將第n/2+1個節點上升到父節點。
- 如果父節點中小節點的個數也為2t了,那麽父節點重復上述分裂過程
2.5 刪除
刪除節點過程:
- 每次刪除一個節點的時候,都需要判斷該節點的父節點,叔叔節點,祖父節點中的子節點個數。如果刪除目標節點以後,父節點,叔叔節點,祖父節點的小節點個數滿足<=2t那麽合並這三個節點為一個節點
- 具體的刪除每個節點的策略:
- 當目標小節點是位於所有小節點中間的時候,那麽就合並該小節點兩邊指向的兩個子節點。
- 當目標小節點是所有小節點之後的節點的時候,那麽就從該節點指出的兩個子樹的節點中選出一個大於t的節點,然後將其換到目標節點處。如果都不夠,那麽先合並兩個子節點,然後提出中間節點。
下面是三種刪除的情況,只有兩層,沒有三層。
3 B+樹
B數,B+樹