0

all! I am trying to implement a simple template class binary search tree. I run into a couple problem with the definitions of functions. The following is my BST class code

#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H

#include <iostream>
#include <stdlib.h>

using namespace std;

template<class T>
class BST
{
    struct TreeNode {
        TreeNode* left;
        TreeNode* right;
        T value;
    };

    //member functions
    void destroyTree(TreeNode* leaf);
    void insert(T key, TreeNode* leaf);
    TreeNode* search(T key, TreeNode* leaf);
    void printInOrder(TreeNode* leaf);
    void printPreOrder(TreeNode* leaf);
    void printPostOrder(TreeNode* leaf);

    //memebr variables
    TreeNode* root;
public:

    enum Traversal { INORDER, PREORDER, POSTORDER };

    BST();
    BST(T key);
    ~BST();

    void insert(T key);
    TreeNode* search(T key);
    void printTree(T option);
    void destroyTree();
};

template <class T>
BST<T>::BST()
{
    root = NULL;
};

template <class T>
BST<T>::BST(T key)
{
    root = new TreeNode;
    root->left = NULL;
    root->right = NULL;
    root->value = key;
};

template <class T>
BST<T>::~BST()
{
    destroyTree();
};

template <class T>
void BST<T>::destroyTree(TreeNode* leaf)
{
    if (leaf->left != NULL) destroyTree(leaf->left);
    if (leaf->right != NULL) destroyTree(leaf->right);
    delete leaf;
    leaf = nullptr;
};

template <class T>
void insert(T key, BST<T>::TreeNode* leaf)
{
    if (leaf->value == key)
    {
        cout << "failed inserting node: duplicate item" << endl;
        return;
    }
    else if (leaf->value < key)
    {
        if (leaf->right != NULL) insert(key, leaf->right);
        else
        {
            TreeNode newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->right = newNode;
        }
    }
    else
    {
        if (leaf->left != NULL) insert(key, leaf->left);
        else
        {
            TreeNode newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->left = newNode;
        }
    }
};

template <class T>
BST<T>::TreeNode* BST<T>::search(T key, TreeNode* leaf)
{
    if (leaf == NULL) return NULL;
    if (leaf->value == key) return leaf;
    else if (leaf->vluae < key) return search(key, leaf->right);
    else return search(key, leaf->left);
};

template <class T>
void printInOrder(TreeNode* leaf)
{
    if (leaf->left != NULL) printInOrder(leaf->left);
    cout << leaf->value << " ";
    if (leaf->right != NULL) printInOrder(leaf->right);
};

template <class T>
void printPreOrder(TreeNode* leaf)
{
    cout << leaf->value << " ";
    if (leaf->left != NULL) printPreOrder(leaf->left);
    if (leaf->right != NULL) printPreOrder(leaf->right);
};

template <class T>
void printPostOrder(TreeNode* leaf)
{
    if (leaf->left != NULL) printPostOrder(leaf->left);
    if (leaf->right != NULL) printPostOrder(leaf->right);
    cout << leaf->value << " ";
};

template <class T>
void BST<T>::insert(int key)
{
    if (this->root == NULL)
    {
        this->root = new TreeNode;
        this->root->left = NULL;
        this->root->right = NULL;
        this->root->value = key;
    }
    else insert(key, root);
};

template <class T>
BST<T>::TreeNode* BST<T>::search(int key)
{
    search(key, this->root);
};

template <class T>
void BST<T>::printTree(int option)
{
    switch (option)
    {
    case BST<T>::INORDER:
        printInOrder(this->root);
        cout << endl;
        break;
    case BST<T>::POSTORDER:
        printPostOrder(this->root);
        cout << endl;
        break;
    case BST<T>::PREORDER:
        printPreOrder(this->root);
        cout << endl;
        break;
    }
};

template <class T>
void BST<T>::destroyTree()
{
    destroyTree(this->root);
};

#endif

As you can see, for the void insert(T key, BST<T>::TreeNode* leaf) and BST<T>::TreeNode* BST<T>::search(T key, TreeNode* leaf) functions I need to do things with TreeNode class like returning an object of it or passing it to a function, which is a nested type defined in class BST. The errors I am getting are at syntax errors, but I don't know where I am doing wrong in the code. Any advice or suggestion would be appreciated!

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
user3377437
  • 183
  • 1
  • 2
  • 9
  • 1
    A bunch of missing `BST::`s, to start with. The `search` functions also need a `typename` in front. – T.C. Feb 13 '15 at 09:56
  • "The errors I am getting are at syntax errors, but I don't know where I am doing wrong in the code." The errors certainly contain this information. But for us to be able to use this info, you need to post the errors. – Angew is no longer proud of SO Feb 13 '15 at 10:01
  • The syntax error for the insert function is `syntax error: identifier 'TreeNode'`. – user3377437 Feb 13 '15 at 10:10

2 Answers2

2

You should:

  • replace every single TreeNode by BST<T>::TreeNode, because there could be different TreeNode definitions so the compiler need to know the one you are talking about.

  • add typename in front of every BST<T>::TreeNode. There could be several different definitions for BST<T>::TreeNode, even some that are not types, so you need to tell the compiler that it is a type.

Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
  • No `typename` requires a qualified name. – Jean-Baptiste Yunès Feb 13 '15 at 10:26
  • 1
    Oh yes, my bad, `BST` is the required qualified name. Sorry for the mistake :) – Rerito Feb 13 '15 at 10:28
  • Thank you for the answer! Could you please elaborate more on the typename keyword? I am a little confused as when is it necessary to use it. Also, after fixing the syntax errors, I'm getting a lot of link errors which I can't read... they are something like `error LNK2019: unresolved external symbol "private: void __thiscall BST::printPreOrder(struct BST::TreeNode *)" (?printPreOrder@?$BST@H@@AAEXPAUTreeNode@1@@Z) referenced in function "public: void __thiscall BST::printTree(int)" (?printTree@?$BST@H@@QAEXH@Z)` – user3377437 Feb 13 '15 at 10:47
  • When you have a nested symbol (like `TreeNode`) in a template, it is almost impossible for the compiler to determine what is the nature of the symbol: think of a definition of a nested variable called `TreeNode`! As template definitions can be sensitive to the template parameters, it is impossible to determine the real nature of a symbol. So if you use it as a type you should claim it so. This is basically the purpose of `typename` (i.e. "the next word IS a type, believe me for the moment!"). – Jean-Baptiste Yunès Feb 13 '15 at 11:34
  • You should qualify your `printPreOrder` definition like in `BST::printPreOrder`. f not you are defining a function named `printPreOrder` not a method `printPreOrder` of the class `BST`. – Jean-Baptiste Yunès Feb 13 '15 at 11:36
1
#include <iostream>
#include <stdlib.h>

using namespace std;

template<class T>
class BST
{
    struct TreeNode {
        TreeNode* left;
        TreeNode* right;
        T value;
    };

    //member functions
    void destroyTree(TreeNode* leaf);
    void insert(T key, TreeNode* leaf);
    TreeNode* search(T key, TreeNode* leaf);
    void printInOrder(TreeNode* leaf);
    void printPreOrder(TreeNode* leaf);
    void printPostOrder(TreeNode* leaf);

    //memebr variables
    TreeNode* root;
public:

    enum Traversal { INORDER, PREORDER, POSTORDER };
    BST();
    BST(T key);
    ~BST();

    void insert(T key);
    TreeNode* search(T key);
    void printTree(T option);
    void destroyTree();
};

template <class T>
BST<T>::BST()
{
    root = NULL;
};

template <class T>
BST<T>::BST(T key)
{
    root = new TreeNode;
    root->left = NULL;
    root->right = NULL;
    root->value = key;
};

template <class T>
BST<T>::~BST()
{
    destroyTree();
};

template <class T>
void BST<T>::destroyTree(TreeNode* leaf)
{
    if (leaf->left != NULL) destroyTree(leaf->left);
    if (leaf->right != NULL) destroyTree(leaf->right);
    delete leaf;
    leaf = nullptr;
};

template <class T>
void BST<T>::insert(T key, typename BST<T>::TreeNode* leaf)
{
    if (leaf->value == key)
    {
        cout << "failed inserting node: duplicate item" << endl;
        return;
    }
    else if (leaf->value < key)
    {
        if (leaf->right != NULL) insert(key, leaf->right);
        else
        {
            BST<T>::TreeNode* newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->right = newNode;
        }
    }
    else
    {
        if (leaf->left != NULL) insert(key, leaf->left);
        else
        {
            BST<T>::TreeNode* newNode = new TreeNode;
            newNode->left = NULL;
            newNode->right = NULL;
            newNode->value = key;
            leaf->left = newNode;
        }
    }
};

template <class T>
typename BST<T>::TreeNode* BST<T>::search(T key, typename BST<T>::TreeNode* leaf)
{
    if (leaf == NULL) return NULL;
    if (leaf->value == key) return leaf;
    else if (leaf->vluae < key) return search(key, leaf->right);
    else return search(key, leaf->left);
};

template <class T>
void printInOrder(typename BST<T>::TreeNode* leaf)
{
    if (leaf->left != NULL) printInOrder(leaf->left);
    cout << leaf->value << " ";
    if (leaf->right != NULL) printInOrder(leaf->right);
};

template <class T>
void printPreOrder(typename BST<T>::TreeNode* leaf)
{
    cout << leaf->value << " ";
    if (leaf->left != NULL) printPreOrder(leaf->left);
    if (leaf->right != NULL) printPreOrder(leaf->right);
};

template <class T>
void printPostOrder(typename BST<T>::TreeNode* leaf)
{
    if (leaf->left != NULL) printPostOrder(leaf->left);
    if (leaf->right != NULL) printPostOrder(leaf->right);
    cout << leaf->value << " ";
};

template <class T>
void BST<T>::insert(T key)
{
    if (this->root == NULL)
    {
        this->root = new TreeNode;
        this->root->left = NULL;
        this->root->right = NULL;
        this->root->value = key;
    }
    else insert(key, root);
};

template <class T>
typename BST<T>::TreeNode* BST<T>::search(T key)
{
    search(key, this->root);
};

template <class T>
void BST<T>::printTree(T option)
{
    switch (option)
    {
        case BST<T>::INORDER:
            printInOrder(this->root);
            cout << endl;
            break;
        case BST<T>::POSTORDER:
            printPostOrder(this->root);
            cout << endl;
            break;
        case BST<T>::PREORDER:
            printPreOrder(this->root);
            cout << endl;
            break;
    }
};

template <class T>
void BST<T>::destroyTree()
{
    destroyTree(this->root);
};

Should work now, but was full of small mistakes like: TreeNode newNode = new TreeNode;, template <class T> void insert instead of template <class T> void BST<T>::insert