简体   繁体   中英

Why can't I return pointer to a node of my BST tree structure? C++

I was coding a BST Tree, and first i made it with integer key, everything worked fine. Then i copied my code and made some changes, i switched integer key to string key and also added one new pointer (because my goal is to create two trees, one with English words and one with their Polish translation) so i tested it just on single tree with string key first and insert function works fine like in the interger tree, but search function is returning some garbage insted of NULL or pointer to node. I dont really know what is a problem here.

I put the code of Integer tree below:

#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
using namespace std;

        typedef struct BST
    {
        int key;
        BST* right;
        BST* left;
    }BST_node;
    
    BST_node* CreateNewNode(int data)  // function that returns new node of my tree
    {
        BST_node* NewNode = new BST_node;
        NewNode->key = data;
        NewNode->right = NULL;
        NewNode->left = NULL;
        return NewNode;
    }
    
    BST_node* bstSearch(BST_node* root, int data) // search function
    {
        if (root == NULL)
            return NULL;
    
        else if (root->key == data)
            return root;
    
        else if (root->key < data)
            bstSearch(root->right, data);
    
        else
            bstSearch(root->left, data);
    }
    
    void bstInsert(BST_node*& root, int data) // insert function
    {
        if (root == NULL)
            root = CreateNewNode(data);
        
        if (data < root->key) 
            bstInsert(root->left, data); 
    
        else if (data > root->key) 
            bstInsert(root->right, data); 
    }
            
    int main()
    {
        ifstream in1("InTest1.txt"); // InTest1.txt:1 2 4 3 5 52 2 4
        BST_node* root = NULL;
        int suppVar;
        while (!in1.eof())
        {
            in1 >> suppVar;
            bstInsert(rootEng, suppVar);
        }
        BST_node* tmp = bstSearch(rootEng, 2);
        if (tmp == NULL)
            cout << "There is no element with given key";
        else
            cout << "key = " << tmp->key;
        
    }

OUT: key = 2

And also i put the code of string key version of my tree below:

#include <iostream>
#include <fstream>
#include <string.h>
#include <string>
using namespace std;

typedef struct BST_str
{
    string key;
    BST_str* right;
    BST_str* left;
    BST_str* engWordPtr; // pointer to node in translation tree (not used yet)
}BST_strNode;

BST_strNode* CreateNewStrNode(string data) // function that returns new node of my tree
{
    BST_strNode* NewNode = new BST_strNode;
    NewNode->key = data;
    NewNode->right = NULL;
    NewNode->left = NULL;
    NewNode->engWordPtr = NULL;
    return NewNode;
}

BST_strNode* bstStrSearch(BST_strNode* root, string data) // search function
{
    if (root == NULL)
        return NULL;

    else if (strcmp(root->key.data(), data.data()) == 0)
        return root;

    else if (strcmp(root->key.data(), data.data()) < 0)
        bstStrSearch(root->right, data);

    else if (strcmp(root->key.data(), data.data()) > 0)
        bstStrSearch(root->left, data);
}

void bstStrInsert(BST_strNode*& root, string data) // insert function
{
    if (root == NULL)
        root = CreateNewStrNode(data);

    else if (strcmp(root->key.data(), data.data()) > 0) 
        bstStrInsert(root->left, data);

    else if (strcmp(root->key.data(), data.data()) < 0)
        bstStrInsert(root->right, data);
}

int main()
{
    ifstream in1("InTest2.txt"); // InTest2.txt:O G X E OH D F I OA H OB OX
    BST_strNode* rootEng = NULL;
    string suppVar;
    while (!in1.eof())
    {
        in1 >> suppVar;
        bstStrInsert(rootEng, suppVar);
    }
    BST_strNode* tmp = bstStrSearch(rootEng, "OXcasdf");
    if (tmp == NULL)
        cout << "There is no element with given key";
    else
        cout << "key = " << tmp->key;
}

OUT: key =

And program crashes, it doesnt matter if i want to search for string that is already there or not, always the same result, probably its returning some garbage instead of node or NULL but i don't really know why it's working on integer tree, but on string tree doesn't. It also generates 3 warnings:

Warning C26495 Variable 'BST_str::engWordPtr' is uninitialized. Always initialize a member variable (type.6).

Warning C26495 Variable 'BST_str::left' is uninitialized. Always initialize a member variable (type.6).

Warning C26495 Variable 'BST_str::right' is uninitialized. Always initialize a member variable (type.6).

And also an exception while debugging:

Exception thrown: read access violation. this was 0x45.

Thanks for the help in advance.

The recursive function bstSearch is incorrect because it does not return a node in each its path of execution

BST_node* bstSearch(BST_node* root, int data) // search function
{
    if (root == NULL)
        return NULL;

    else if (root->key == data)
        return root;

    else if (root->key < data)
        bstSearch(root->right, data);

    else
        bstSearch(root->left, data);
}

The last if else statements should look like

    else if (root->key < data)
        return bstSearch(root->right, data);

    else
        return bstSearch(root->left, data);

Also for the function designed for strings there is no need to use the C function strcmp. The function could be defined the following way

BST_strNode* bstStrSearch( BST_strNode* root, const string &data) // search function
{
    if (root == NULL)
        return NULL;

    else if ( root->key == data )
        return root;

    else if ( root->key < data )
        return bstStrSearch(root->right, data);

    else 
        return bstStrSearch(root->left, data);
}

Pay attention to that the condition of the while loop

while (!in1.eof())
{
    in1 >> suppVar;
    bstStrInsert(rootEng, suppVar);
}

is incorrect. The eof state can occur after this statement

    in1 >> suppVar;

Instead you should write

while ( in1 >> suppVar)
{
    bstStrInsert(rootEng, suppVar);
}

Note when compiled, the compiler should print a warning along the lines of:

warning: control may reach end of non-void function

in reference to bstStrInsert . Indeed, looking at the function definition, the two recursive branches don't return a value.

To prevent the warning (and this sort of error in general), you can use a local variable to hold the result, and have a single return.

Additionally, the functions should be rewritten as member function of the BST node class. You can also use templates (and template specializations) rather than creating separate, unrelated BST classes for each key type.

BST_Node<String>* BST_Node<String>::search(BST_strNode* root, string data) // search function
{
    BST_Node<String>* result = NULL;

    if (root) {
        if (root->key == data)
            result = root;
        else if (root->key < data)
            result = bstStrSearch(root->right, data);
        else if (root->key > data)
            result = bstStrSearch(root->left, data);
    }

    return result;
}

Additional

When printing a message, be sure to include a newline. This can be done with a newline in the string, but better is to output std::endl , which will also flush the output buffer (if output is buffered, which it probably is).

Importing all of std into the current namespace is fine for one-offs, sample and practice code, but shouldn't be done in production. Importing specific symbols (such as std::cin , std::cout and std::endl ) is fine and unlikely to cause collisions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM