B樹的刪除操作

2021-06-29 02:56:09 字數 3129 閱讀 6727

把b樹壓縮成陣列的結構, 二維的樹是由 一維的陣列 進化(拉伸)而來的,所以我們先還原成 一維陣列 可以簡化對刪除操作的思考(如前趨值、後趨值的概念就是一維陣列中的)。

實質上,b樹的刪除和二叉樹的刪除很相似,都是用其左/右分支的最大值/最小值來覆蓋(刪除)當前要刪除的關鍵字,然後再遞迴刪除此左/右分支的此關鍵字。

而無論是二叉樹還是b樹,也無論是刪除還是插入,最後的任務都落在葉子結點上!

首先,每次刪除開始之前,我們考查根結點,看是否符合合併的規則,如果合併,此時樹的高度減1,這是樹高度減少的唯一途徑,此外合併也是為了應付要刪除的關鍵字也可能就是根結點的情況。

接著,從根(如果合併就從新的根開始)開始刪除,查詢當前結點。

在刪除的過程中,可能會出現兩種情況,

1)要刪除的關鍵字在當前結點中,如果其左/右分支的根結點(下一次遞迴新的根結點)的關鍵字個數至少為 t 個(也是為了★),就用其左/右分支的最大值/最小值來覆蓋(刪除)當前要刪除的關鍵字,然後再遞迴刪除此左/右分支的此關鍵字(以此左/右分支的根結點為新的根,★);如果都為 t -1 個,就不能保證在下次遞迴呼叫時包括關鍵字的子樹根(新的根)的關鍵字數至少為t(除了根結點外),所以應該根結點下拉合併再刪除。這麼做的目的是不破壞b樹的結構,就像二叉樹的刪除一樣。

2)要刪除的關鍵字不在當前結點中,但是我們可以確定關鍵字所在的(當前結點的)分支。看此分支根結點關鍵字個數是否等於 t - 1 個,如果是,就向兄弟結點經父節點借關鍵字(向左借/向右借/下拉合併)——(借過之後,所借的兄弟結點的關鍵字個數減1,所以要保證所借結點的關鍵字個數至少是 t ,否則就要把根結點關鍵字下拉合併),借和合併的目的也是為了保證在下一次遞迴時新的根關鍵字個數至少為 t 。然後以此左/右分支的根結點為新的根(也是至少為 t )遞迴向下查詢。

當然如果至少為 t 個,不借也不合併了,遞迴向下刪除即可。

這麼做,都是為了保證此分支的根結點的關鍵字個數至少為 t ,從而為將來可能發生的下拉做好準備。

★:從上面可以看出,我們必須時刻保證包含要刪除關鍵字的根結點的關鍵字數量至少為t,這樣做就是為了確保合併的成功(所謂合併,就是根結點的乙個關鍵字下拉到此關鍵字的左子結點中且把右子結點合併到左子結點中——當然,前提是此時左結點無法從其相鄰兄弟結點借關鍵字,即相鄰兄弟結點的關鍵字個數皆為 t - 1 個)。使得在每次遞迴呼叫前,程式都能保證包括關鍵字的子樹根的關鍵字數至少為t(除了根結點外)。

具體做法如下:

**如下:

// 將y、root->k[pos]、z合併到y節點,並釋放z節點(前提是 y,z 各有m-1個節點)

void btree_merge_child(btree_node *root, int pos, btree_node *y, btree_node *z)

y->k[m-1] = root->k[pos]; // k[pos]下降為y的 中間 節點

// 如果z非葉子,需要拷貝pointer

if(false == z->is_leaf)

}// 根的k[pos]下降到y中,更新根的key和pointer

for(int j = pos + 1; j < root->num; j++)

root->num -= 1; //根的關鍵字個數減 1

free(z);}

// 刪除入口,即每次刪除乙個數都要先檢查根及其兩個子女是否需要合併(高度減1的唯一方法)—注意合併後的根

btree_node *btree_delete(btree_node *root, int target)

else

} else }

/* root至少有個t個關鍵字,保證不會回溯。

在當前結點中,就覆蓋並向下遞迴刪除;

不在當前結點中,就要麼就把子結點通過當前結點(父節點)周轉 或者 合併,然後再向下遞迴刪除*/

void btree_delete_nonone(btree_node *root, int target)

root->num -= 1;

} else

} else

else if(z->num > m - 1)

else

} else

btree_node *p = null;

if(i > 0)

if(y->num == m - 1)

else if(i < root->num && z->num > m - 1)

else if(i > 0)

else

btree_delete_nonone(y, target);

} else }}

} //尋找rightmost,以root為根的最大關鍵字

int btree_search_predecessor(btree_node *root)

return y->k[y->num-1];

} // 尋找leftmost,以root為根的最小關鍵字

int btree_search_successor(btree_node *root)

return z->k[0];

} // z向y借節點,將root->k[pos]下降至z,將y的最大關鍵字上公升至root的pos處

void btree_shift_to_right_child(btree_node *root, int pos,

btree_node *y, btree_node *z)

z->k[0]= root->k[pos];

root->k[pos] = y->k[y->num-1];

if(false == z->is_leaf)

z->p[0] = y->p[y->num];

}y->num -= 1;

} // y向借z節點,將root->k[pos]下降至y,將z的最小關鍵字上公升至root的pos處

void btree_shift_to_left_child(btree_node *root, int pos,

btree_node *y, btree_node *z)

if(false == z->is_leaf)

} z->num -= 1;

}

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 樹作為全域性變...

B樹插入刪除操作

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