bnode.cpp
来自「数据结构与程序设计教材源码 数据结构与程序设计教材源码」· C++ 代码 · 共 419 行
CPP
419 行
template <class Record, int order>
B_node<Record, order>::B_node()
{
count = 0;
}
template <class Record, int order>
void B_tree<Record, order>::recursive_print(B_node<Record, order> *current,
int indent)
{
int i;
if (current != NULL) {
for (i = 0; i < indent; i++) cout << " ";
cout << ": (";
for (i = 0; i < current->count; i++) cout << current->data[i] << ",";
cout << ")\n";
for (i = 0; i <= current->count; i++)
recursive_print(current->branch[i], indent + 1);
}
}
template <class Record, int order>
Error_code B_tree<Record, order>::recursive_search_tree(
B_node<Record, order> *current, Record &target)
/*
Pre: current is either NULL or points to a subtree of the
B_tree.
Post: If the Key of target is not in the subtree, a code of not_present
is returned.
Otherwise, a code of success is returned and
target is set to the corresponding Record of
the subtree.
Uses: recursive_search_tree recursively and search_node
*/
{
Error_code result = not_present;
int position;
if (current != NULL) {
result = search_node(current, target, position);
if (result == not_present)
result = recursive_search_tree(current->branch[position], target);
else
target = current->data[position];
}
return result;
}
template <class Record, int order>
Error_code B_tree<Record, order>::search_node(
B_node<Record, order> *current, const Record &target, int &position)
/*
Pre: current points to a node of a B_tree.
Post: If the Key of target is found in *current, then a code of
success is returned, the parameter position is set to the index
of target, and the corresponding Record is copied to
target. Otherwise, a code of not_present is returned, and
position is set to the branch index on which to continue the search.
Uses: Methods of class Record.
*/
{
position = 0;
while (position < current->count && target > current->data[position])
position++; // Perform a sequential search through the keys.
if (position < current->count && target == current->data[position])
return success;
else
return not_present;
}
template <class Record, int order>
Error_code B_tree<Record, order>::push_down(
B_node<Record, order> *current,
const Record &new_entry,
Record &median,
B_node<Record, order> *&right_branch)
/*
Pre: current is either NULL or points to a node of a B_tree.
Post: If an entry with a Key matching that of new_entry is in the subtree
to which current points, a code of duplicate_error is returned.
Otherwise, new_entry is inserted into the subtree: If this causes the
height of the subtree to grow, a code of overflow is returned, and the
Record median is extracted to be reinserted higher in the B-tree,
together with the subtree right_branch on its right.
If the height does not grow, a code of success is returned.
Uses: Functions push_down (called recursively), search_node,
split_node, and push_in.
*/
{
Error_code result;
int position;
if (current == NULL) { // Since we cannot insert in an empty tree, the recursion terminates.
median = new_entry;
right_branch = NULL;
result = overflow;
}
else { // Search the current node.
if (search_node(current, new_entry, position) == success)
result = duplicate_error;
else {
Record extra_entry;
B_node<Record, order> *extra_branch;
result = push_down(current->branch[position], new_entry,
extra_entry, extra_branch);
if (result == overflow) { // Record extra_entry now must be added to current
if (current->count < order - 1) {
result = success;
push_in(current, extra_entry, extra_branch, position);
}
else split_node(current, extra_entry, extra_branch, position,
right_branch, median);
// Record median and its right_branch will go up to a higher node.
}
}
}
return result;
}
template <class Record, int order>
void B_tree<Record, order>::push_in(B_node<Record, order> *current,
const Record &entry, B_node<Record, order> *right_branch, int position)
/*
Pre: current points to a node of a B_tree.
The node *current is not full and
entry belongs in *current at index position.
Post: entry has been inserted along with its right-hand branch
right_branch into *current at index position.
*/
{
for (int i = current->count; i > position; i--) { // Shift all later data to the right.
current->data[i] = current->data[i - 1];
current->branch[i + 1] = current->branch[i];
}
current->data[position] = entry;
current->branch[position + 1] = right_branch;
current->count++;
}
template <class Record, int order>
void B_tree<Record, order>::split_node(
B_node<Record, order> *current, // node to be split
const Record &extra_entry, // new entry to insert
B_node<Record, order> *extra_branch,// subtree on right of extra_entry
int position, // index in node where extra_entry goes
B_node<Record, order> *&right_half, // new node for right half of entries
Record &median) // median entry (in neither half)
/*
Pre: current points to a node of a B_tree.
The node *current is full, but if there were room, the record
extra_entry with its right-hand pointer extra_branch would belong
in *current at position position,
0 <= position < order.
Post: The node *current with extra_entry and pointer extra_branch at
position position are divided into nodes *current and *right_half
separated by a Record median.
Uses: Methods of struct B_node, function push_in.
*/
{
right_half = new B_node<Record, order>;
int mid = order/2; // The entries from mid on will go to right_half.
if (position <= mid) { // First case: extra_entry belongs in left half.
for (int i = mid; i < order - 1; i++) { // Move entries to right_half.
right_half->data[i - mid] = current->data[i];
right_half->branch[i + 1 - mid] = current->branch[i + 1];
}
current->count = mid;
right_half->count = order - 1 - mid;
push_in(current, extra_entry, extra_branch, position);
}
else { // Second case: extra_entry belongs in right half.
mid++; // Temporarily leave the median in left half.
for (int i = mid; i < order - 1; i++) { // Move entries to right_half.
right_half->data[i - mid] = current->data[i];
right_half->branch[i + 1 - mid] = current->branch[i + 1];
}
current->count = mid;
right_half->count = order - 1 - mid;
push_in(right_half, extra_entry, extra_branch, position - mid);
}
median = current->data[current->count - 1]; // Remove median from left half.
right_half->branch[0] = current->branch[current->count];
current->count--;
}
template <class Record, int order>
Error_code B_tree<Record, order>::recursive_remove(
B_node<Record, order> *current, const Record &target)
/*
Pre: current is either NULL or
points to the root node of a subtree of a B_tree.
Post: If a Record with Key matching that of target belongs to the subtree,
a code of success is returned and the corresponding node is removed
from the subtree so that the properties of a B-tree are maintained.
Otherwise, a code of not_present is returned.
Uses: Functions search_node, copy_in_predecessor,
recursive_remove (recursive-ly), remove_data, and restore.
*/
{
Error_code result;
int position;
if (current == NULL) result = not_present;
else {
if (search_node(current, target, position) == success) { // The target is in the current node.
result = success;
if (current->branch[position] != NULL) { // not at a leaf node
copy_in_predecessor(current, position);
recursive_remove(current->branch[position],
current->data[position]);
}
else remove_data(current, position); // Remove from a leaf node.
}
else result = recursive_remove(current->branch[position], target);
if (current->branch[position] != NULL)
if (current->branch[position]->count < (order - 1) / 2)
restore(current, position);
}
return result;
}
template <class Record, int order>
void B_tree<Record, order>::copy_in_predecessor(
B_node<Record, order> *current, int position)
/*
Pre: current points to a non-leaf node in a B-tree with an
entry at position.
Post: This entry is replaced by its immediate predecessor
under order of keys.
*/
{
B_node<Record, order> *leaf = current->branch[position]; // First go left from the current entry.
while (leaf->branch[leaf->count] != NULL)
leaf = leaf->branch[leaf->count]; // Move as far rightward as possible.
current->data[position] = leaf->data[leaf->count - 1];
}
template <class Record, int order>
void B_tree<Record, order>::remove_data(B_node<Record, order> *current,
int position)
/*
Pre: current points to a leaf node in a B-tree with an entry at position.
Post: This entry is removed from *current.
*/
{
for (int i = position; i < current->count - 1; i++)
current->data[i] = current->data[i + 1];
current->count--;
}
template <class Record, int order>
void B_tree<Record, order>::restore(B_node<Record, order> *current,
int position)
/*
Pre: current points to a non-leaf node in a B-tree; the node to which
current->branch[position] points has one too few entries.
Post: An entry is taken from elsewhere to restore the minimum number of
entries in the node to which current->branch[position] points.
Uses: move_left, move_right, combine.
*/
{
if (position == current->count) // case: rightmost branch
if (current->branch[position - 1]->count > (order - 1) / 2)
move_right(current, position - 1);
else
combine(current, position);
else if (position == 0) // case: leftmost branch
if (current->branch[1]->count > (order - 1) / 2)
move_left(current, 1);
else
combine(current, 1);
else // remaining cases: intermediate branches
if (current->branch[position - 1]->count > (order - 1) / 2)
move_right(current, position - 1);
else if (current->branch[position + 1]->count > (order - 1) / 2)
move_left(current, position + 1);
else
combine(current, position);
}
template <class Record, int order>
void B_tree<Record, order>::move_left(B_node<Record, order> *current,
int position)
/*
Pre: current points to a node in a B-tree with more than the minimum
number of entries in branch position and one too few entries in branch
position - 1.
Post: The leftmost entry from branch position has moved into
current, which has sent an entry into the branch position - 1.
*/
{
B_node<Record, order> *left_branch = current->branch[position - 1],
*right_branch = current->branch[position];
left_branch->data[left_branch->count] = current->data[position - 1]; // Take entry from the parent.
left_branch->branch[++left_branch->count] = right_branch->branch[0];
current->data[position - 1] = right_branch->data[0]; // Add the right-hand entry to the parent.
right_branch->count--;
for (int i = 0; i < right_branch->count; i++) { // Move right-hand entries to fill the hole.
right_branch->data[i] = right_branch->data[i + 1];
right_branch->branch[i] = right_branch->branch[i + 1];
}
right_branch->branch[right_branch->count] =
right_branch->branch[right_branch->count + 1];
}
template <class Record, int order>
void B_tree<Record, order>::move_right(B_node<Record, order> *current,
int position)
/*
Pre: current points to a node in a B-tree with more than the minimum
number of entries in branch position and one too few entries
in branch position + 1.
Post: The rightmost entry from branch position has moved into
current, which has sent an entry into the branch position + 1.
*/
{
B_node<Record, order> *right_branch = current->branch[position + 1],
*left_branch = current->branch[position];
right_branch->branch[right_branch->count + 1] =
right_branch->branch[right_branch->count];
for (int i = right_branch->count ; i > 0; i--) { // Make room for new entry.
right_branch->data[i] = right_branch->data[i - 1];
right_branch->branch[i] = right_branch->branch[i - 1];
}
right_branch->count++;
right_branch->data[0] = current->data[position]; // Take entry from parent.
right_branch->branch[0] = left_branch->branch[left_branch->count--];
current->data[position] = left_branch->data[left_branch->count];
}
template <class Record, int order>
void B_tree<Record, order>::combine(B_node<Record, order> *current,
int position)
/*
Pre: current points to a node in a B-tree with entries in the branches
position and position - 1, with too few to move entries.
Post: The nodes at branches position - 1 and position have been combined
into one node, which also includes the entry formerly in current at
index position - 1.
*/
{
int i;
B_node<Record, order> *left_branch = current->branch[position - 1],
*right_branch = current->branch[position];
left_branch->data[left_branch->count] = current->data[position - 1];
left_branch->branch[++left_branch->count] = right_branch->branch[0];
for (i = 0; i < right_branch->count; i++) {
left_branch->data[left_branch->count] = right_branch->data[i];
left_branch->branch[++left_branch->count] =
right_branch->branch[i + 1];
}
current->count--;
for (i = position - 1; i < current->count; i++) {
current->data[i] = current->data[i + 1];
current->branch[i + 1] = current->branch[i + 2];
}
delete right_branch;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?