我有一个奇怪的错误,在我的程序执行了twoThreeTree(或B-Tree)的split方法之后,子节点变为null,并且创建的新节点中保存的任何整数值都消失了(n1和n2 ,如果传递的节点是root,则为p。我已经多次检查了分割方法最后的root,root.left和root.right(或p,p.left和p.right)的值,它们都很好,但是第二个程序退出split方法并返回insertItem方法(即,在第188行调用split方法,并在第189行调用方法后再次检查值)Node不再具有任何整数值且其子节点为null。
twoThreeTree.cpp
#include <iostream>
#include "twoThreeTree.h"
twoThreeTree::twoThreeTree() {
root = NULL;
}
//helper method
void twoThreeTree::inOrder() {
inOrder(root);
}
//modified recursive LVR in order traversal
void twoThreeTree::inOrder(Node* ptr){
...
} //end else
}
/*
*takes a leaf node with three values and gives the parent node the middle value.
*calls itself recursively when the '3-Node'parent inherents an extra value
*/
void twoThreeTree::split(Node* ptr){
toString(ptr);
Node p;
/*
*special case, if the node passed is the root
*else p is equal to the parent
*/
if (ptr->parent == 0) {
p = Node(ptr->middleValue);
p.isLeaf = false;
} //end if
else {
p = *ptr->parent;
} //end else
/*
*two new nodes inhereting the small and large values of the
*inital node, the intial node will be dispoded of at the end of the method
*/
Node* n1 = new Node(ptr->smallValue);
Node* n2 = new Node(ptr->largeValue);
int item = ptr->middleValue;
/*
*not neccessary. at the moment, only used to test for the root node
*/
n1->parent = &p;
n2->parent = &p;
toString(n1);
toString(n2);
/*
*will only happen with the recursive calls below. this segment splits a
*'4-node' into two '2-nodes'
*/
if (ptr->isLeaf == false) {
n1->isLeaf = false;
n2->isLeaf = false;
n1->left = ptr->left;
n1->right = ptr->middle;
n2->left = ptr->right;
n2->right = ptr->extra;
} //end if
/*
*the parent will now temporarily become a '4-node' where-in its left child
*equals the lowest value, middle second lowest, right second highest,
*extra the highest value, and the '4-node' will be split again recursively
*/
if (p.isThreeNode == true) {
if (item < p.smallValue) {
p.middleValue = p.smallValue;
p.smallValue = item;
p.extra = p.right;
p.right = p.middle;
p.left = n1;
p.middle = n2;
} //end if
else if (item < p.largeValue) {
p.middleValue = item;
p.extra = p.right;
p.right = n2;
p.middle = n1;
} //end else if
else { //item > p.largeValue
p.middleValue = p.largeValue;
p.largeValue = item;
p.extra = n2;
p.right = n1;
} //end else
split(&p);
} //end if
/*
*the parent will become a '3-Node' in this case. p.left and
*p.right already exist and adjusting them is just a matter of understanding where
*our current node is in relation to the parent (ie. if the item value is less than
*p.smallvalue then we know the current node is to the left of the parent and the right
*side does not need adjusting)
*/
else if (p.parent != 0) { //p.isTwoNode == true
p.isThreeNode = true;
if (item < p.smallValue) {
p.largeValue = p.smallValue;
p.smallValue = item;
p.left = n1;
p.middle = n2;
} //end if
else { //item > p.smallValue
p.largeValue = item;
p.right = n2;
p.middle = n1;
} //end else
} //end else
/*
*in this case the node passed to the method was the root and along with normal
*splitting methods, the root must be changed
*/
else {
std::cout << "this one" << std::endl;
p.left = n1;
p.right = n2;
root = &p;
//delete ptr; do not know if this is neccesary
}
} //end split
//helper method, special case for root
void twoThreeTree::insertItem(int item){
if (root == NULL){
root = new Node(item);
return;
}
insertItem(root, item);
}
/*
*will recursively call itself until a leaf node is hit. once a leaf
*node is hit a value will be assigned, if a middle value is assigned the
*node will be split
*/
void twoThreeTree::insertItem(Node* ptr, int item) {
toString(ptr);
if (ptr->smallValue == 0){
std::cout << "small value equals zero" << std::endl;
ptr->smallValue = item;
return;
}
//locate the leaf in which the new item belongs
if (ptr->isLeaf == true) {
if (ptr->largeValue == 0) {
if (item > ptr->smallValue) {
ptr->largeValue = item;
} //end if
else { //the item is smaller than the smallValue
ptr->largeValue = ptr->smallValue;
ptr->smallValue = item;
} //end else
} //end if
else { //if there are two pieces of data
if (item < ptr->smallValue) {
ptr->middleValue = ptr->smallValue;
ptr->smallValue = item;
} //end if
else if (item < ptr->largeValue) {
ptr->middleValue = item;
} //end else if
else {
ptr->middleValue = ptr->largeValue;
ptr->largeValue = item;
} //end else
split(ptr);
} //end else
} //end if
else if (ptr->isThreeNode == true) {
if (item < ptr->smallValue) {
insertItem(ptr->left, item);
} //end if
else if (item < ptr->largeValue) {
insertItem(ptr->middle, item);
} //end else if
else {
insertItem(ptr->right, item);
} //end else
} //end else if
else {
if (item < ptr->smallValue) {
insertItem(ptr->left, item);
} //end if
else {
insertItem(ptr->right, item);
} //end else
} //end else
} //end insertItem
void twoThreeTree::toString(Node* ptr){
std::cout << "address: " << ptr << " small: " << ptr->smallValue << " middle: " << ptr->middleValue << " large: " << ptr->largeValue << std::endl;
}
twoThreeTree.h
#ifndef TWOTHREETREE_H
#define TWOTHREETREE_H
#include <iostream>
/*
*node structure with 5 pointers
*/
struct Node {
int smallValue,
middleValue,
largeValue;
Node* left;
Node* middle;
Node* right;
Node* extra;
Node* parent;
bool isLeaf,
isThreeNode;
Node() {
smallValue = 0;
middleValue = 0;
largeValue = 0;
left = 0;
middle = 0;
right = 0;
extra = 0;
parent = 0;
isLeaf = true;
isThreeNode = false;
}
Node(int smallValue) {
this->smallValue = smallValue;
middleValue = 0;
left = 0;
middle = 0;
right = 0;
extra = 0;
parent = 0;
largeValue = 0;
isLeaf = true;
isThreeNode = false;
}
};
class twoThreeTree {
/*
private:
Node root;
void inOrder (Node& ref) {};
void insertItem(Node& ref, int item) {};
*/
public: //all values temporarily public
Node*root;
void inOrder (Node* ptr);
void insertItem(Node* ptr, int item);
twoThreeTree();
void inOrder();
int findItem(Node* ptr, int target);
void split(Node* ptr);
void toString(Node* ptr);
void insertItem(int item);
};
#endif
主要
#include <iostream>
#include "twoThreeTree.h"
int main() {
int size;
std::cout << "Enter the size (between 2^6 and 2^13): "; //ignore any specified values
std::cin >> size;
int startingValue = rand() % 10000;
twoThreeTree tree; //initialize twoThreeTreeClass
tree.insertItem(startingValue); //not neccessary, done for debugging purposes
std::cout << "starting value: " << startingValue << std::endl;
for (int i = 0; i < size; i++){
int debug = rand() % 10000;
std::cout << "random number: " << debug << std::endl;
std::cout << "root address: " << tree.root << " root small value: " << tree.root->smallValue << std::endl;
tree.insertItem(debug);
}
tree.inOrder();
}
标准输出是:
起始值:41
输入:8467
root:0064A380小:41中:0大:8467
输入:6334
--split--
root:0064A380小:41中:6334大:8467
n1:0064A54A小:41中:0大:0
n2:0064A5A8小:8467“”
p:0018F444小:6334“”
root:0018F444小:6334“”
--main--
root:0018F444 small:-85899340“”
非常令人沮丧的问题将会感谢任何有助于阐明问题的帮助