Место чтения нарушения доступа B-Tree

У меня странная ошибка, когда после того, как моя программа выполняет метод split для twoThreeTree (или B-Tree), дочерние элементы становятся нулевыми, и любые целочисленные значения, сохраненные в новых созданных узлах, исчезают (n1 и n2 и p если переданный узел является корневым). Я проверил значения root, root.left и root.right (или p, p.left и p.right) в самом конце метода split, и все они в порядке, но во втором случае программа завершается. метод split и возвращается к методу insertItem (т. е. метод split вызывается в строке 188, и я снова проверяю значения после вызова метода в строке 189). Узел больше не имеет целочисленных значений, и его дочерние элементы равны нулю.

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
корень: 0064A380 маленький: 41 средний: 0 большой: 8467
вход: 6334
—Трещина—
корень: 0064A380 маленький: 41 средний: 6334 большой: 8467
n1: 0064A54A маленький: 41 средний: 0 большой: 0
n2: 0064A5A8 маленький: 8467 «»
p: 0018F444 маленький: 6334 «»
root: 0018F444 small: 6334 «»
—главный—
root: 0018F444 small: -85899340 «»

действительно расстраивающая проблема была бы признательна за любую помощь, проливающую свет на проблему

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector