B树访问违规读取位置

时间:2015-12-21 14:05:46

标签: c++ pointers nodes b-tree

我有一个奇怪的错误,在我的程序执行了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“”

非常令人沮丧的问题将会感谢任何有助于阐明问题的帮助

0 个答案:

没有答案