1

Thinking there is an issue with my root declaration, the three errors are showing up in my insert function, default constructor and destructor.

If I #include .cpp file: There is an issue with my insert function and constructing the tree properly. I am watching my local variables and root is behaving strangely - after the first value is added root is pointing to something that has no data. (I'm quite new to C++ so please bear with me, this is my first time creating a template class & a binary search tree)

It's throwing an exception each time it reaches the line while(p->data != item).

Here's my insert function:

    template <class Item>
void Tree<Item>::insert(Item item)
{
    Node<Item> *new_node = new Node<Item>();
    new_node->data = item;

    if (root == nullptr)
    {
        root = new_node;
    }
    else
    {
        Node<Item> *q = nullptr;
        Node<Item> *p = root;
        while (p != nullptr && q->data != item)
        {
            q = p;
            if (item < p->data)
            {
                q = p->lchild;
            }
            else if (item > p->data)
            {
                q = p->rchild;
            }
        }
        if (q->data == item)
        {
            cout << "Duplicate Data" << endl;
        }
        else
        {
            if (item > q->data)
            {
                q->rchild = new_node;
            }
            else
            {
                q->lchild = new_node;
            }
        }
    }
}

Header:

#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

template <class Item>
struct Node
{
    //Default constructor for Node
    //Purpose: Initialize all values
    //Parameters: None
    //Returns: None
    Node();

    //Parameterized constructor for Node
    //Purpose: Initialize all values
    //Parameters: a data Item, and Node pointers for left and right children
    //Returns: None
    Node(Item, Node<Item>*, Node<Item>*);

    //variables
    Item data;
    Node<Item> *lchild;
    Node<Item> *rchild;
};

template <class Item>
class Tree
{

public:
    //Default constructor for Tree
    //Purpose: Initialize all values
    //Parameters: None
    //Returns: None
    Tree();

    //Copy constructor
    //Purpose: create new Tree
    //Parameters: A Tree object
    //Returns: Tree
    Tree(const Tree&);

    //copy
    //Purpose: To copy values
    //Parameters: Node pointer
    //Returns: None
    void copy(Node<Item>*);

    //chop
    //Purpose: Delete tree
    //Parameters: Node pointer
    //Returns: None
    void chop(Node<Item>*);

    //Destructor
    //Purpose: Clean up data, delete tree
    //Parameters: None
    //Returns: None
    ~Tree();

    //operator=
    //Purpose: Overload assignment operator
    //Parameters: a const ref to a Tree object
    //Returns: Tree
    const Tree<Item>&operator=(const Tree&);

    //insert
    //Purpose: To add a value to tree
    //Parameters: A const reference to an Item
    //Returns: None
    void insert(Item);

    //inOrderTraverse
    //Purpose: To traverse the tree in order
    //Parameters: A Node pointer
    //Returns: None
    //void inOrderTraverse(Item);


private:
    Node<Item> *root;
};

And here is my Tree class:

   #include "Tree.h"

template <class Item>
Node<Item>::Node()
{
    data = 0;
    lchild = nullptr;
    rchild = nullptr;
}

template <class Item>
Node<Item>::Node(Item _data, Node<Item> *_lchild, Node<Item> *_rchild)
{
    data = _data;
    lchild = _lchild;
    rchild = _rchild;
}

template <class Item>
Tree<Item>::Tree()
{
    root = nullptr;
}

template <class Item>
void Tree<Item>::copy(Node<Item> *c)
{
    if (c)
    {
        insert(c->data);
        copy(c->lchild);
        copy(c->rchild);
    }
}

template <class Item>
void Tree<Item>::chop(Node<Item> *c)
{
    if (c)
    {
        chop(c->lchild);
        chop(c->rchild);
        delete c;
    }
}

template <class Item>
Tree<Item>::Tree(const Tree& t)
{
    root = nullptr;
    copy(t.root);
}

template <class Item>
Tree<Item>::~Tree()
{
    chop(root);
}

template <class Item>
const Tree<Item>&Tree<Item>::operator=(const Tree& t)
{
    if (this != &t)
    {
        chop(root);
        root = nullptr;
        copy(t.root);
    }
    return *this;
}

template <class Item>
void Tree<Item>::insert(Item item)
{
    Node<Item> *new_node = new Node<Item>();
    new_node->data = item;

    if (root == nullptr)
    {
        root = new_node;
    }
    else
    {
        Node<Item> *p = root;
        Node<Item> *q = nullptr;
        while (p->data != item)
        {
            q = p;
            if (item < p->data)
            {
                p = p->lchild;
            }
            else if (item > p->data)
            {
                p = p->rchild;
            }
        }
        if (p-> data == item)
        {
            cout << "Duplicate Data" << endl;
        }
        else 
        {
            if (item < q->data)
            {
                q->lchild = new_node;
            }
            else
            {
                q->rchild = new_node;
            }
        }

    }
}

Main:

#include "Tree.h"

int main()
{
    //variables for data
    string file;
    ifstream infile(file);
    Tree<int> myTree;
    int d = 0;

    //ask user to enter filename
    cout << "Please enter the file you wish to open: " << endl;
    getline(cin, file);
    infile.open(file.c_str());

    //make sure filename is valid
    while (!infile)
    {
        cout << "Error opening file, please enter the name of the file you wish to open: " << endl;
        getline(cin, file);
        infile.open(file.c_str());
    }

    //if file is good, build tree
    while (!infile.eof())
    {
        myTree.insert(d);
        infile >> d;
        cout << d << endl;
    }

    system("PAUSE");
    return 0;
}
valiano
  • 16,433
  • 7
  • 64
  • 79
user5407906
  • 87
  • 1
  • 8
  • do not incude .cpp file!!! –  Oct 25 '15 at 19:32
  • @GRC Ah. I did that initially because I kept getting unresolved external symbol errors... – user5407906 Oct 25 '15 at 19:36
  • @GRC It looks like the errors are related to my root declaration because they're showing up in the insert function, default constructor and destructor. – user5407906 Oct 25 '15 at 19:40
  • include your .h file as well. –  Oct 25 '15 at 19:49
  • @GRC I don't know if this makes a difference, but the specific error says: error LNK2019: unresolved external symbol "public: void __thiscall Tree::insert(int)" (?insert@?$Tree@H@@QAEXH@Z) referenced in function _main – user5407906 Oct 25 '15 at 20:02
  • @GRC Am I not creating a tree object properly in main? – user5407906 Oct 25 '15 at 20:22
  • The error is microsoft error I cannot reproduce it, I am bit confused with templates since I have not used them in a long time. –  Oct 25 '15 at 22:30
  • @GRC I appreciate your time and help, I ended up just making a non-template class and it's not giving me that error now. – user5407906 Oct 25 '15 at 23:01

2 Answers2

1

In the while loop condition shouldn't it be

while (p != nullptr && p->data != item)

q is just a null pointer and [ q->data != item ] will always be true.

1

You have several problems with your algorithm, I will point to few of them.

if (root == nullptr)
{
    root = new_node;
}

takes care of condition that root is not null. Down the code you have

Node<Item> *p = root;

and

while (p != nullptr && p->data != item)

one error here is already pointed in another answer but p cannot be null since at this point p is same as root and p is never changing, so you are constantly pointing at root.

q = p // I would do q = root;

should be outside the loop. Inside of loops should be something like this:

while(q != nullptr) {
  if(newNode->data < q->data) {
    q = q->leftChild;
  } else if(newNode->data > q->data) {
    q = q->rightChild;
  } else {
    cout << "ERROR: item already exists";
    return 1;
  }
}
  • I tried your code and it printed the list fine (still with no "duplicate" message), but as I'm watching my local variables there is nothing being saved in "p", because nothing is being saved in root. The tree is not being constructed accurately. Any ideas why? – user5407906 Oct 25 '15 at 18:33
  • where you declare `Node root` does it say `Node root = nullptr` –  Oct 25 '15 at 18:37
  • Yeah, I am editing my original post to add my constructors and such – user5407906 Oct 25 '15 at 18:38
  • can you post your main method as well? –  Oct 25 '15 at 18:57