0

So I'm implementing a templated binary tree dictionary as a class that inherits from an abstract Dictionary class, and I have a problem with my add function that I can't figure out.

Basically, my tree has nodes that have both a key and value, and pointers to its parent, left child, and right child. The code for the node is

struct bNode {
    K key;
    V value;
    bNode* left;
    bNode* right;
    bNode* parent;
};

(I know using shared_ptr is better than raw pointers but it wasn't required for this project) The tree also has a member pointer bNode* root.

To test my tree, I add elements to it and call display after each one. So far, displaying an empty list works properly, as does displaying a list with one element and with two elements. When I add a third, though, and call display, it breaks...

Here's the code for the add function

void add(K key, V value) override {
    // if list is empty, create new root node
    if (!root){
        root = new bNode;
        root->key = key;
        root->value = value;
        return;
    }
    bNode* node = root;
    // travel down tree, checking each node on the way
    while (true){
        // if node exists with passed-in key, change value to passed-in value
        if (node->key == key){
            node->value = value;
            return;
        }
        // if key < or > node and node has a left / right child, travel left / right branch
        // if node doesn't have a left / right child, create one and pass in key
        if (key < node->key){
            if (node->left){
                node = node->left;
            } else {
                node->left = new bNode;
                node->left->parent = node;
                node->left->key = key;
                node->left->value = value;
                return;
            }
        } else {
            if (node->right){
                node = node->right;
            } else {
                node->right = new bNode;
                node->right->parent = node;
                node->right->key = key;
                node->right->value = value;
                return;
            }
        }
    }
}

here's display

void display() const override {
    if (!root){
        return;
    }
    displayHelper(root);
    cout << endl;
}

and here's displayHelper

void displayHelper(bNode* node) const {
    cout << "(" << node->key << ", " << node->value << ") ";
    if (node->left){
        cout << "displaying left... <" << node->key << "> ";
        displayHelper(node->left);
    }
    if (node->right){
        cout << "displaying right... <" << node->key << "> ";
        displayHelper(node->right);
    }
}

The lines that cout "displaying right" and "displaying left" were my attempts to bugfix, as it shouldn't run unless the function is about to display another node. This all worked as expected after displaying the first 2 nodes; however, at the third node, it would display that element, and then print "displaying left <*3rd node's key>...", then crash and give me a segmentation fault.

As far as I can tell, this means that for some reason the code is running as if the third added node, which should be a leaf node, actually has children, but then crashing when it tries to read the member variables for nonexistant nodes.

I can't figure out what's causing the bug, as this is all pretty simple code! Any help would be greatly appreciated!

EDIT: here's an example snippet of code demonstrating the problem;

BSTDictionary<string, int> t;
t.display();
t.add("e", 5);
t.display();
t.add("b", 20);
t.display();
t.add("c", 12);
t.display();
return 0;

when run, the output looks like

(e,5)

(e,5) displaying left... (e) (b,20)

(e,5) displaying left... (e) (b,20) displaying right... (b) (c,12) displaying left... (c)

Process returned -1073741819 (0xC0000005) execution time : 1.993 s

There should be no left child of the node containing (c,12), yet the compiler is trying to run as if there is.

aitalo
  • 13
  • 3
  • The right tool to solve such problems is your debugger. You should step through your code line-by-line *before* asking on Stack Overflow. For more help, please read [How to debug small programs (by Eric Lippert)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). At a minimum, you should \[edit] your question to include a [Minimal, Complete, and Verifiable](http://stackoverflow.com/help/mcve) example that reproduces your problem, along with the observations you made in the debugger. – πάντα ῥεῖ Dec 19 '16 at 22:10
  • I did try to run through the debugger but it also kept stepping into the display function and immediately crashing with a segmentation fault – aitalo Dec 19 '16 at 22:13
  • Please provide a [mcve]. It could be that you never initialize `root` – 463035818_is_not_an_ai Dec 19 '16 at 22:16
  • added! As I said there is a member variable in the private section of the class for root, formatted `bNode* root`, and in the constructor for the Dictionary I have the line `root = nullptr;`, so I don't think that's it unfortunately – aitalo Dec 19 '16 at 22:21
  • 1
    I don't see where the left and right pointers are initialized to null when a new node is created. – Mikel F Dec 19 '16 at 22:22
  • Oh, I might have forgotten to do that! Let me try initializing them in the add function and see if that helps! – aitalo Dec 19 '16 at 22:25
  • @aitalo If you are running in the debugger and it segfaults, you should be able to see exactly what it was doing before the crash. `bt` in gdb, or something like "Stack trace" if you are using a visual debugger. – 0x5453 Dec 19 '16 at 22:26
  • @Mikel F That fixed it! I feel really dumb for missing that, thanks! – aitalo Dec 19 '16 at 22:27

1 Answers1

1

You need to make sure that you initialize all leaf node pointers in an object to nullptr unless you are immediately assigning them to something meaningful.

Mikel F
  • 3,567
  • 1
  • 21
  • 33