The problem lies in the insert method with two parameters.
The function, insert(char letter, string code), calls insert(TreeNode *node, char letter, char code). However it does not assign the left or right child as the node. The insert method with three parameters should create a new node. Then this node should be assigned as either a left or a right child.
#include "tree.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (root) {
if (node->left) {
return empty_tree(node->left);
}
if (node->right) {
return empty_tree(node->right);
}
delete node;
}
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
TreeNode *temp = nullptr;
if (node) {
for (string::size_type i = 0; i < code.length(); i++) {
//temp = node;
if (code[i] == '.') {
if (node->left) {
node = node->left;
}
else {
insert(temp, letter, code[i]);
node->left = temp;
}
}
else {
if (node->right) {
node = node->right;
}
else {
return insert(temp, letter, code[i]);
node->right = temp;
}
}
}
}
/*else {
return insert();
}*/
}
void BinaryTree::insert() {
if (!root) {
root= new TreeNode();
root->letter = '*';
root->left = nullptr;
root->right = nullptr;
root->code = "*";
}
}
void BinaryTree::insert(TreeNode *node, char letter, char code) {
if (!node) {
node = new TreeNode();
node->letter = letter;
node->left = nullptr;
node->right = nullptr;
node->code += code;
}
}
void BinaryTree::print_tree() {
return print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left) {
print_tree(tree->left);
}
if (tree->right) {
print_tree(tree->right);
}
cout << "Node is " << tree->letter << " and in Morse Code is " << tree->code << endl << endl;
}
}
Below is the file containing main. The morse-code.txt file just has the alphabet letters in order from a to z. Each line has one letter, followed by a space, followed by the morse code.
#include "tree.h"
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::endl;
int main() {
std::string code;
std::ifstream infile;
char letter;
BinaryTree tree;;
infile.open("morse-code.txt");
if (!infile) {
std::cout << "File unable to open" << std::endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert();
while (std::getline(infile, code)) {
tree.insert(code[0], code.substr(2, code.length()-2));
cout << code << endl;
}
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
}
text file
a .-
b -...
c -.-.
d -..
e .
f ..-.
g --.
h ....
i ..
j .---
k -.-
l -.--
m --
n -.
o ---
p .--.
q --.-
r .-.
s ...
t -
u ..-
v ...-
w .--
x -..-
y -.--
z --..
tree.h
#ifndef _TREE_H
#define _TREE_H
//#include <iostream>
//#include <fstream>
#include <string>
using std::string;
class BinaryTree {
private:
struct TreeNode {
char letter;
string code;
TreeNode *left;
TreeNode *right;
}; TreeNode *root;
public:
BinaryTree();
~BinaryTree();
void insert();
void insert(TreeNode *new_node, char letter, char code);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree(TreeNode *node);
void print_tree();
};
#endif
I think that insert isn't the only problems you have with your code. Your empty_tree is incorrect (will not free all of the memory, since you return prematurely. The specific part of the code you have wrong is the following line of your code: "return insert(temp, letter, code[i]);"
The rest of your code looks fine.
It should look something like this instead:
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) return;
delete node;
empty_tree(node->left );
empty_tree(node->right);
/* See Jerry's solution below. */
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
if (!root) /* do something*/;
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (node->left)
insert(&node->left, letter, code[i]);
node = node->left;
}
else {
if (!node->right)
insert(&node->right, letter, code[i]);
node = node->right
}
}
}
void BinaryTree::insert(TreeNode **node, char letter, string code) {
*node = new TreeNode();
(*node)->letter = letter;
(*node)->left = nullptr;
(*node)->right = nullptr;
(*node)->code = code;
}
In tree.h:
typedef struct _TreeNode {
char letter;
string code;
struct _TreeNode *left;
struct _TreeNode *right;
} TreeNode; TreeNode *root;
I *compiled the following code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
typedef struct _TreeNode {
char letter;
string code;
struct _TreeNode *left;
struct _TreeNode *right;
} TreeNode;
class BinaryTree {
private:
TreeNode *root;
public:
BinaryTree();
~BinaryTree();
void insert();
void insert(TreeNode **new_node, char letter, string code);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree(TreeNode *node);
void print_tree();
};
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) return;
delete node;
empty_tree(node->left );
empty_tree(node->right);
}
void BinaryTree::insert(char letter, string code) {
TreeNode *node = root;
if (!root) insert();
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (!node->left)
insert(&node->left, letter, code.substr(0,i));
node = node->left;
} else {
if (!node->right)
insert(&node->right, letter, code.substr(0,i));
node = node->right;
}
}
}
void BinaryTree::insert() {
root = new TreeNode();
root->letter = '*';
root->left = nullptr;
root->right = nullptr;
root->code = "*";
}
void BinaryTree::insert(TreeNode **node, char letter, string code) {
*node = new TreeNode();
(*node)->letter = letter;
(*node)->left = nullptr;
(*node)->right = nullptr;
(*node)->code = code;
}
void BinaryTree::print_tree() {
return print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left ) print_tree(tree->left );
cout << "Node is " << tree->letter << " and in Morse Code is "
<< tree->code << endl << endl;
if (tree->right) print_tree(tree->right);
}
}
int main() {
string code;
ifstream infile;
char letter;
BinaryTree tree;
infile.open("morse-code.txt");
if (!infile) {
cout << "File unable to open" << endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert();
while (std::getline(infile, code)) {
tree.insert(code[0], code.substr(2, code.length()-2));
cout << code << endl;
}
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
}
So the problem was in my tree_driver.cpp file. Most of the problems contained in that file were in the insert function with two parameters. Below is the working code.
tree_driver.cpp
#include "tree.h"
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
BinaryTree::BinaryTree() {
root = nullptr;
}
BinaryTree::~BinaryTree() {
empty_tree(root);
}
void BinaryTree::empty_tree(TreeNode *node) {
if (!node) {
if (node->left) {
empty_tree(node->left);
}
if (node->right) {
empty_tree(node->right);
}
delete node;
}
}
//The following member function contains the most alterations
void BinaryTree::insert(char letter, string code) {
if (!root) {
insert(root, letter, code, true);
}
else {
TreeNode *node = root;
for (string::size_type i = 0; i < code.length(); i++) {
if (code[i] == '.') {
if (!node->left) {
if (i == code.length() - 1) {
insert(node->left, letter, code.substr(0, i + 1), true);
}
else {
insert(node->left, letter, code.substr(0, i + 1), false);
}
}
node = node->left;
if (node->left) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
if (!node->left) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
}
else if (code[i] == '-') {
if (!node->right) {
if (i == code.length() - 1) {
insert(node->right, letter, code.substr(0, i + 1), true);
}
else {
insert(node->right, letter, code.substr(0, i + 1), false);
}
}
node = node->right;
if (node->right) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
if (!node->right) {
if (i == code.length() - 1) {
node->letter = letter;
}
}
}
}
}
}
void BinaryTree::insert(TreeNode *&node, char letter, string code, bool last) {
if (last) {
node = new TreeNode();
node->letter = letter;
node->right = nullptr;
node->left = nullptr;
node->code = code;
}
if (!last) {
node = new TreeNode();
node->letter = '\0';
node->right = nullptr;
node->left = nullptr;
node->code = code;
}
}
void BinaryTree::print_tree() {
print_tree(root);
}
void BinaryTree::print_tree(TreeNode *tree) {
if (tree) {
if (tree->left) {
print_tree(tree->left);
}
cout << "Node is " << tree->letter << " and in Morse Code is " << tree->code << endl << endl;
if (tree->right) {
print_tree(tree->right);
}
}
}
tree_tester.
#include "tree.h"
#include <iostream>
#include <fstream>
#include <string>
using std::cout;
using std::endl;
int main() {
std::string code_main;
std::ifstream infile;
BinaryTree tree;;
infile.open("morse-code.txt");
if (!infile) {
std::cout << "File unable to open" << std::endl;
}
else {
cout << "morse-code.txt\n\n";
tree.insert('0', "*");
while (std::getline(infile, code_main)) {
tree.insert(code_main[0], code_main.substr(2, code_main.length()-2));
cout << code_main << endl;
}
infile.close();
cout << "\n******Tree Representation******\n\n";
tree.print_tree();
}
system("pause");
return 0;
}
tree.h
#ifndef _TREE_H
#define _TREE_H
#include <string>
using std::string;
class BinaryTree {
private:
struct TreeNode {
string letter;
string code;
TreeNode *left;
TreeNode *right;
}; TreeNode *root;
public:
BinaryTree();
~BinaryTree();
/*void insert();*/
void insert(TreeNode *&new_node, char letter, string code, bool last);
void insert(char letter, string code);
void empty_tree(TreeNode *node);
void print_tree();
void print_tree(TreeNode *node);
};
#endif
Related
I am currently learning C++ and have been researching BST. I took upon myself a task within a workbook but have been struggling to finish the implementation.
I am not allowed to change the header file or any of the function definitions but I am allowed to add helpers.
I have attempted adding some helpers, but whenever I run the test file, no words are inserted into the tree.
I was hoping someone would be able to help me or give me guidance on finishing the implementation.
Any help on the other functions would be greatly appreciated!
My Header File:
#pragma once
#include <iostream>
#include <string>
// Node of the tree
struct Node
{
std::string data;
Node *left = nullptr;
Node *right = nullptr;
};
class BST
{
private:
Node *root = nullptr;
public:
BST();
BST(std::string word);
BST(const BST &rhs);
~BST();
void insert(std::string word);
void remove(std::string word);
bool exists(std::string word) const;
std::string inorder() const;
std::string preorder() const;
std::string postorder() const;
bool operator==(const BST &other) const;
bool operator!=(const BST &other) const;
};
My BST file:
#include "bst.h"
#include <iostream>
#include <string>
using namespace std;
string HelperInsert(Node **root, std::string word)
{
if (*root == nullptr)
{
// Create new node
*root = new Node;
// Set new value
(*root)->data = word;
// Set branches to nullptr
(*root)->left = nullptr;
(*root)->right = nullptr;
}
else
if (word < (*root)->data)
{
HelperInsert(&(*root)->left, word);
}
else
{
if (word > (*root)->data)
{
HelperInsert(&(*root)->right, word);
}
}
}
void HelperExists(Node *root, string word)
{
Node *temp = new Node;
temp = root;
// Run the loop untill temp points to a NULL pointer.
while(temp != NULL)
{
if(temp->data == word)
{
cout<<"True "<<endl;
}
// Shift pointer to left child.
else if(temp->data > word)
temp = temp->left;
// Shift pointer to right child.
else
temp = temp->right;
}
cout<<"\n False";
return;
}
string Helpwr(Node *root)
{
if(root == nullptr)
{
return "";
}
else
{
return inorderHelper(root->left)
+ root->data + " "
+ inorderHelper(root->right);
}
}
void HelperPreOrder(Node *root)
{
if ( root !=nullptr)
{
cout << root->data << " ";
HelperPreOrder(root->left);
HelperPreOrder(root->right);
}
}
void HelperPostorder(Node *root)
{
if (root!=nullptr)
{
HelperPostorder(root->left);
HelperPostorder(root->right);
cout << root->data<< endl;
return;
}
}
BST::BST()
{
root= nullptr;
}
// Creates a binary tree by copying an existing tree
BST::BST(const BST &rhs)
{
}
void BST::insert(string word)
{
HelperInsert(*root, word);
}
void BST::remove(string word)
{
}
bool BST::exists(string word) const
{
HelperExists(root, word);
return true;
}
std::string BST::inorder() const
{
string res = inorderHelper(root);
int len = res.length();
if(len >= 1 && res[len -1] == ' ')
{
res.pop_back();
}
return res;
}
std::string BST::preorder() const
{
HelperPreOrder(root);
return std::string("");
}
std::string BST::postorder() const
{
HelperPostorder(root);
return std::string("");
}
bool BST::operator==(const BST &other) const
{
return true;
}
bool BST::operator!=(const BST &other) const
{
return true;
}
My test file:
tree = new BinarySearchTree();
// Test 3 - insertion check
tree->insert("fish");
tree->insert("aardvark");
tree->insert("zeebra");
str = tree->inorder();
if (str != string("aardvark fish zeebra"))
cerr << "test 3 failed" << endl;
else
cout << "Test 3 passed" << endl;
// Test 4 - exists check
if (tree->exists("zeebra") && tree->exists("fish") && !tree->exists("bird") && !tree->exists("snake"))
cout << "Test 4 passed" << endl;
else
cerr << "test 4 failed" << endl;
Seems like an issue of not storing the string words correctly:
your insert method is as follows:
void insert(std::string word);
Which means a value of the string is passed, not a reference.
In order to store the string, you'll have to create a copy of the string and store it in memory:
string HelperInsert(Node **root, std::string word)
{
if (*root == nullptr)
{
// Create new node
*root = new Node;
// Set new value
(*root).data = new std:string(word); // note the setting of a string pointer here!
// Set branches to nullptr
(*root)->left = nullptr;
(*root)->right = nullptr;
}
else
if (word < (*root)->data)
{
HelperInsert(&(*root)->left, word);
}
else
{
if (word > (*root)->data)
{
HelperInsert(&(*root)->right, word);
}
}
}
Do not forget to delete the string when removing nodes, in order to prevent mempory leaks.
Good luck!
I've built an AVL Tree out of an old Binary Tree in C++ for practice and it is not working correctly. I think it may not be updating the height of the nodes correctly but I can't figure out the root of the issue ( I'm 90% sure it has to do with the helper functions getHeight, setHeight, getBalance).
Some example test runs..:
adding 6,3,4 causes a Right Rotation it should cause a RL rotation
similarly adding 20,30,25 causes a LL rotation when it should cause a LR rotation
adding 20,30,10,5,6 causes two seperate Right rotations when it should cause a RL rotation
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
using namespace std;
struct intNode {
int data;
intNode * Left;
intNode * Right;
int height;
intNode(int input, intNode * iLeft= NULL, intNode * iRight = NULL) {
data = input;
Left = iLeft;
Right = iRight;
height = 0;
}
};
int getHeight(intNode* temp) {
if (temp == NULL)
return 0;
return temp->height;
}
void setHeight(intNode * temp)
{
int hLeft = getHeight(temp->Left);
int hRight = getHeight(temp->Right);
temp->height = 1 + max(hLeft, hRight);
}
int getBalance(intNode * temp) {
if (temp == NULL) {
return 0;
} else {
return getHeight(temp->Left) - getHeight(temp->Right);
}
}
struct intTree {
intNode * root;
intTree();
void addNode(int input);
void addNode(int input, intNode *& root);
void print();
void print(intNode *input);
intNode * balanceTree(intNode *& sub);
intNode * rotateRight(intNode *& sub);
intNode * rotateLeft(intNode *& sub);
};
void intTree::print(intNode *input) {
if (input != NULL) {
print(input->Left);
cout << input->data << endl;
print(input->Right);
}
}
void intTree::print() {
print(root);
}
intNode * intTree::rotateRight(intNode *& subTree) {
intNode * newRoot = subTree->Left;
subTree->Left = newRoot->Right;
newRoot->Right = subTree;
setHeight(subTree);
setHeight(newRoot);
return newRoot;
}
intNode * intTree::rotateLeft(intNode *& subTree) {
intNode * newRoot = subTree->Right;
subTree->Right = newRoot->Left;
newRoot->Left = subTree;
setHeight(subTree);
setHeight(newRoot);
return newRoot;
}
intNode* intTree::balanceTree(intNode *& subTree) {
setHeight(subTree);
if (getBalance(subTree) == 2 && getBalance(subTree->Right) < 0) {
cout << "RL" << endl;
subTree->Left = rotateLeft(subTree->Left);
return rotateRight(subTree);
} else if (getBalance(subTree) == 2) { // RR
cout << "RR" << endl;
return rotateRight(subTree);
} else if (getBalance(subTree) == -2 && getBalance(subTree->Left) > 0) { // LR
cout << "LR" << endl;
subTree->Right = rotateRight(subTree->Right);
return rotateLeft(subTree);
} else if (getBalance(subTree) == -2) { // LL
cout << "LL" << endl;
return rotateLeft(subTree);
} else {
return subTree; // balanced
}
}
intTree::intTree() {
root = NULL;
}
void intTree::addNode(int input, intNode *& temp) {
if (temp == NULL) {
temp = new intNode(input);
} else if (input < temp->data) {
cout <<" added to the left" << endl;
addNode(input,temp->Left);
} else if (input > temp->data) {
cout <<" added to the right" << endl;
addNode(input, temp->Right);
}
temp = balanceTree(temp);
}
void intTree::addNode(int input) {
addNode(input, root);
}
void read() {
string num;
int balance, input;
int i = 0;
intTree * intBST = new intTree();
while (i != 10) {
cout << "number?" << endl;
cin >> input;
intNode *tempInt= new intNode(input);
intBST->addNode(input);
i++;
}
cout << "Finished reading in files" << endl;
while (true) {
string userInput;
cin >> userInput;
if (userInput == "Exit") {
cout << "Goodbye!" << endl;
return;
}
if (userInput == "Print") {
intBST->print();
return;
}
}
}
void main() {
read();
return 0;
}
I would appreciate any tips/help on further figuring this out. Let me know if I can provide any more information to help.
Thank you.
I want to turn this single .cpp file into multiple ones but I'm having trouble doing so. I'm getting undeclared identifier and 'children' : is not a member of 'Node' compiler errors.
Here is my original entire code:
#include <iostream>
#include <vector>
using namespace std;
class Node {
public:
Node();
~Node() {}
char content();
void setContent(char c);
bool wordMarker();
void setWordMarker();
Node* findChild(char c);
void appendChild(Node* child);
vector<Node*> children();
private:
char m_Content;
bool m_Marker;
vector<Node*> m_Children;
};
class Trie {
public:
Trie();
~Trie();
void addWord(string s);
bool searchWord(string s);
void deleteWord(string s);
private:
Node* root;
};
Node::Node()
{
m_Content = ' '; m_Marker = false;
}
char Node::content()
{
return m_Content;
}
void Node::setContent(char c)
{
m_Content = c;
}
bool Node::wordMarker()
{
return m_Marker;
}
void Node::setWordMarker()
{
m_Marker = true;
}
void Node::appendChild(Node* child)
{
m_Children.push_back(child);
}
vector<Node*> Node::children()
{
return m_Children;
}
Node* Node::findChild(char c)
{
for (int i = 0; i < m_Children.size(); i++)
{
Node* tmp = m_Children.at(i);
if (tmp->content() == c)
{
return tmp;
}
}
return NULL;
}
Trie::Trie()
{
root = new Node();
}
Trie::~Trie()
{
// Free memory
}
void Trie::addWord(string s)
{
Node* current = root;
if (s.length() == 0)
{
current->setWordMarker(); // an empty word
return;
}
for (int i = 0; i < s.length(); i++)
{
Node* child = current->findChild(s[i]);
if (child != NULL)
{
current = child;
}
else
{
Node* tmp = new Node();
tmp->setContent(s[i]);
current->appendChild(tmp);
current = tmp;
}
if (i == s.length() - 1)
current->setWordMarker();
}
}
bool Trie::searchWord(string s)
{
Node* current = root;
while (current != NULL)
{
for (int i = 0; i < s.length(); i++)
{
Node* tmp = current->findChild(s[i]);
if (tmp == NULL)
return false;
current = tmp;
}
if (current->wordMarker())
return true;
else
return false;
}
return false;
}
// Test program
int main()
{
Trie* trie = new Trie();
trie->addWord("Hello");
trie->addWord("Balloon");
trie->addWord("Ball");
if (trie->searchWord("Hell"))
cout << "Found Hell" << endl;
if (trie->searchWord("Hello"))
cout << "Found Hello" << endl;
if (trie->searchWord("Helloo"))
cout << "Found Helloo" << endl;
if (trie->searchWord("Ball"))
cout << "Found Ball" << endl;
if (trie->searchWord("Balloon"))
cout << "Found Balloon" << endl;
delete trie;
}
My attempt:
node.h
#ifndef NODE_INCLUDED
#define NODE_INCLUDED
class Node {
public:
Node();
~Node() {}
char content();
void setContent(char c);
bool wordMarker();
void setWordMarker();
Node* findChild(char c);
void appendChild(Node* child);
vector<Node*> children();
private:
char m_Content;
bool m_Marker;
vector<Node*> m_Children;
};
#endif // NODE_INCLUDED
trie.h
#ifndef TRIE_INCLUDED
#define TRIE_INCLUDED
class Trie {
public:
Trie();
~Trie();
void addWord(string s);
bool searchWord(string s);
void deleteWord(string s);
private:
Node* root;
};
#endif //TRIE_INCLUDED
node.cpp
#include "node.h"
#include <iostream>
#include <vector>
using namespace std;
Node::Node()
{
m_Content = ' '; m_Marker = false;
}
char Node::content()
{
return m_Content;
}
void Node::setContent(char c)
{
m_Content = c;
}
bool Node::wordMarker()
{
return m_Marker;
}
void Node::setWordMarker()
{
m_Marker = true;
}
void Node::appendChild(Node* child)
{
m_Children.push_back(child);
}
vector<Node*> Node::children()
{
return m_Children;
}
Node* Node::findChild(char c)
{
for (int i = 0; i < m_Children.size(); i++)
{
Node* tmp = m_Children.at(i);
if (tmp->content() == c)
{
return tmp;
}
}
return NULL;
}
trie.cpp
Trie::Trie()
{
root = new Node();
}
Trie::~Trie()
{
// Free memory
}
void Trie::addWord(string s)
{
Node* current = root;
if (s.length() == 0)
{
current->setWordMarker(); // an empty word
return;
}
for (int i = 0; i < s.length(); i++)
{
Node* child = current->findChild(s[i]);
if (child != NULL)
{
current = child;
}
else
{
Node* tmp = new Node();
tmp->setContent(s[i]);
current->appendChild(tmp);
current = tmp;
}
if (i == s.length() - 1)
current->setWordMarker();
}
}
bool Trie::searchWord(string s)
{
Node* current = root;
while (current != NULL)
{
for (int i = 0; i < s.length(); i++)
{
Node* tmp = current->findChild(s[i]);
if (tmp == NULL)
return false;
current = tmp;
}
if (current->wordMarker())
return true;
else
return false;
}
return false;
}
main.cpp
#include "node.h"
#include <iostream>
#include <vector>
using namespace std;
// Test program
#include "node.h" //is this needed?
#include "trie.h" //is this needed?
int main()
{
Trie* trie = new Trie();
trie->addWord("Hello");
trie->addWord("Balloon");
trie->addWord("Ball");
if (trie->searchWord("Hell"))
cout << "Found Hell" << endl;
if (trie->searchWord("Hello"))
cout << "Found Hello" << endl;
if (trie->searchWord("Helloo"))
cout << "Found Helloo" << endl;
if (trie->searchWord("Ball"))
cout << "Found Ball" << endl;
if (trie->searchWord("Balloon"))
cout << "Found Balloon" << endl;
delete trie;
}
So here is what I got working, I comment on things I have added or removed.
node.h
#ifndef NODE_INCLUDED
#define NODE_INCLUDED
#include <vector> //Class Node uses vector so it should be included
#include <iostream> //Class Node uses iostream so it should be included
class Node {
public:
Node();
~Node() {}
char content();
void setContent(char c);
bool wordMarker();
void setWordMarker();
Node* findChild(char c);
void appendChild(Node* child);
std::vector<Node*> children();
private:
char m_Content;
bool m_Marker;
std::vector<Node*> m_Children;
};
#endif // NODE_INCLUDED
trie.h
#ifndef TRIE_INCLUDED
#define TRIE_INCLUDED
#include "node.h" //Class Trie uses Node so it should include it
#include <string> //Class Node uses string so it should include it
class Trie {
public:
Trie();
~Trie();
void addWord(string s);
bool searchWord(string s);
void deleteWord(string s);
private:
Node* root;
};
#endif //TRIE_INCLUDED
node.cpp
#include "node.h"
//#include <iostream>
//#include <vector>
using namespace std;
//Here you got all includes right but they should be in the header file!
Node::Node()
{
m_Content = ' '; m_Marker = false;
}
char Node::content()
{
return m_Content;
}
void Node::setContent(char c)
{
m_Content = c;
}
bool Node::wordMarker()
{
return m_Marker;
}
void Node::setWordMarker()
{
m_Marker = true;
}
void Node::appendChild(Node* child)
{
m_Children.push_back(child);
}
vector<Node*> Node::children()
{
return m_Children;
}
Node* Node::findChild(char c)
{
for (int i = 0; i < m_Children.size(); i++)
{
Node* tmp = m_Children.at(i);
if (tmp->content() == c)
{
return tmp;
}
}
return NULL;
}
trie.cpp
#include "trie.h" //Trie.cpp should at least contain its header file
Trie::Trie()
{
root = new Node();
}
Trie::~Trie()
{
// Free memory
}
void Trie::addWord(string s)
{
Node* current = root;
if (s.length() == 0)
{
current->setWordMarker(); // an empty word
return;
}
for (int i = 0; i < s.length(); i++)
{
Node* child = current->findChild(s[i]);
if (child != NULL)
{
current = child;
}
else
{
Node* tmp = new Node();
tmp->setContent(s[i]);
current->appendChild(tmp);
current = tmp;
}
if (i == s.length() - 1)
current->setWordMarker();
}
}
bool Trie::searchWord(string s)
{
Node* current = root;
while (current != NULL)
{
for (int i = 0; i < s.length(); i++)
{
Node* tmp = current->findChild(s[i]);
if (tmp == NULL)
return false;
current = tmp;
}
if (current->wordMarker())
return true;
else
return false;
}
return false;
}
main.cpp
//#include "node.h" //You don't use Node here, so don't include it!
//Keep your code simple
#include <iostream>
#include <vector>
using namespace std;
// Test program
//#include "node.h" //is this needed? Not needed because you don't use
//its declarations directly here and
//you had it declared before
#include "trie.h" //is this needed? Yes, it is. You use that class
//directly here, so it should include it
int main()
{
Trie* trie = new Trie();
trie->addWord("Hello");
trie->addWord("Balloon");
trie->addWord("Ball");
if (trie->searchWord("Hell"))
cout << "Found Hell" << endl;
if (trie->searchWord("Hello"))
cout << "Found Hello" << endl;
if (trie->searchWord("Helloo"))
cout << "Found Helloo" << endl;
if (trie->searchWord("Ball"))
cout << "Found Ball" << endl;
if (trie->searchWord("Balloon"))
cout << "Found Balloon" << endl;
delete trie;
}
By the way, you should not use using namespace in header files as it is a bad practice
I am creating a priority queue that utilizes a binary search tree for my Data Structures class. But when I attempt to output the queue I always get 0. I have looked over my DeleteLargest and Dequeue member function but I can't find the mistake
Test.cpp
#include <iostream>
#include "CTree.h"
#include "PriorityQueueBST.h"
using namespace std;
int main()
{
int num, input, output;
cout << "Enter number of elements: ";
cin >> num;
PriorityQueueBST p;
for (int x = 0; x < num; x++)
{
cout << "Enter number " << x + 1
<< " of " << num << ": ";
cin >> input;
p.Enqueue(input);
}
for (int y = 0; y < num; y++)
{
cout << "Outputting number " << y + 1
<< " of " << num << ": ";
if(p.IsEmpty())
{
break; //we are done (this is an error!)
}
output = p.Dequeue();
cout << output << endl;
}
system("pause");
return 0;
//CTree* tr = new CTree();
//
//for (int i = 0; i < 3; i++)
// tr->Add();
//tr->View();
//system("pause");
//return 0;
}
BST Declaration file
//#ifndef CTREE_H
//#define CTREE_H
//using namespace std;
struct TreeNode
{
int info;
TreeNode* leftLink;
TreeNode* rightLink;
};
class CTree
{
private:
void AddItem( TreeNode*&, TreeNode*);
void DisplayTree(TreeNode*);
void Retrieve(TreeNode*&, TreeNode*,bool&);
void Destroy(TreeNode*&);
public:
CTree();
~CTree();
void Add();
void View();
bool IsEmpty();
int DeleteLargest(TreeNode*&);
TreeNode *tree;
};
//#endif
BST Implementation file
#include <iostream>
#include <string>
using namespace std;
#include "CTree.h"
CTree::CTree()
{
tree = NULL;
}
CTree::~CTree()
{
Destroy(tree);
}
void CTree::Destroy(TreeNode*& tree)
{
if (tree != NULL)
{
Destroy(tree->leftLink);
Destroy(tree->rightLink);
delete tree;
}
}
bool CTree::IsEmpty()
{
if(tree == NULL)
{
return true;
}
else
{
return false;
}
}
void CTree::Add()
{
TreeNode* newPerson = new TreeNode();
/*cout << "Enter the person's name: ";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cin.getline(newPerson->name, 20);*/
/* cout << "Enter the person's contribution: ";
cin >> newPerson->info;*/
/*bool found = false;*/
newPerson->leftLink = NULL;
newPerson->rightLink = NULL;
/*Retrieve(tree, newPerson, found);
if (found)
cout << "info allready entered\n";
else*/
AddItem(tree, newPerson);
}
void CTree::View()
{
if (IsEmpty())
{
cout<<"The list is empy";
}
else
{
DisplayTree(tree);
}
};
void CTree::AddItem( TreeNode*& ptr, TreeNode* newPer )
{
if (ptr == NULL)
{
ptr = newPer;
}
else if ( newPer->info < ptr->info)
AddItem(ptr->leftLink, newPer);
else
AddItem(ptr->rightLink, newPer);
}
void CTree::DisplayTree(TreeNode* ptr)
{
if (ptr == NULL)
return;
DisplayTree(ptr->rightLink);
cout << ptr->info << endl; //cout<<ptr->name<<" "<<"$"<<ptr->info <<endl;
DisplayTree(ptr->leftLink);
}
void CTree::Retrieve(TreeNode*& ptr, TreeNode* newPer, bool& found)
{
{
if (ptr == NULL)
{
found = false; // item is not found.
}
else if ( newPer->info < ptr->info)
{
Retrieve(ptr->leftLink, newPer, found);
}
// Search left subtree.
else if (newPer->info > ptr->info)
{
Retrieve(ptr->rightLink, newPer, found);// Search right subtree.
}
else
{
//newPer.info = ptr->info; // item is found.
found = true;
}
}
}
int CTree::DeleteLargest(TreeNode*& tr)
{
int largest = 0;;
TreeNode* prev;
TreeNode* cur;
prev = NULL;
cur = tr;
if (tr == NULL)
{
cout << "The tree is empty"<<endl;
}
else if (tr->rightLink == NULL)
{
largest = tr->info;
}
else
{
prev = tr;
tr = tr->rightLink;
DeleteLargest(tr);
}
return largest;
}
Priority Queue Declaration
//#include <iostream>
//using namespace std;
//#include "SortedLinkedList.h"
#ifndef PRIORITYQUEUESLL__H
#define PRIORITYQUEUESLL__H
class PriorityQueueBST
{
public:
PriorityQueueBST();
~PriorityQueueBST();
void Enqueue(int);
int Dequeue();
bool IsEmpty();
private:
CTree* ourTree;
//sslNode* head;
};
#endif
Priority Queue Implementation
#include <iostream>
using namespace std;
#include "CTree.h"
#include "PriorityQueueBST.h"
PriorityQueueBST::PriorityQueueBST()
{
ourTree = new CTree();
//head = NULL;
}
PriorityQueueBST::~PriorityQueueBST()
{
}
void PriorityQueueBST::Enqueue(int dataToEnter)
{
ourTree->Add();
}
int PriorityQueueBST::Dequeue()
{
//check for empty??
return ourTree->DeleteLargest(ourTree->tree);
}
bool PriorityQueueBST::IsEmpty()
{
return ourTree->IsEmpty();
}
Your output is always 0 because in
int CTree::DeleteLargest(TreeNode*& tr)
{
int largest = 0;;
TreeNode* prev;
TreeNode* cur;
prev = NULL;
cur = tr;
if (tr == NULL)
{
cout << "The tree is empty"<<endl;
}
else if (tr->rightLink == NULL)
{
largest = tr->info;
}
else
{
prev = tr;
tr = tr->rightLink;
DeleteLargest(tr);
}
return largest;
}
you only set largest to something potentially != 0 if tr->rightlink is NULL. Otherwise you recur and set the largest variable local to another invocation of the function. That change is lost when the recursion goes up again, and in the topmost invocation, largest is still 0.
In the last line of the else branch, you should either
largest = DeleteLargest(tr);
or
return DeleteLargest(tr);
Another problem is that, despite its name, deleteLargest doesn't actually delete anything, so with the above, you would still always get the same value.
I still can't find the largest number in my tree, but now I am really not complicating it, I think it should work, there is no error, but it just won't show me in the console. Anyone got an idea? I am getting really frustrated.
Here is my entire code:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot)
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);;
}
void PrintTree(Node* theRoot)
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";;
PrintTree(theRoot->rChildptr);
}
}
T Largest( Node* theRoot)
{
if ( root == NULL ){
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
cout<<theRoot->data;
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(2);
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(10);
myBT->AddItem(15);
myBT->PrintTree();
myBT->Largest();
}
and here is the part that is supposed to find the largest number (the child that is far right down):
T Largest( Node* theRoot)
{
if ( root == NULL ){
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
cout<<theRoot->data;
};
There are two problems in your code in Largest():
It looks like you wanted to execute two statements in the else clause, but you didn't use braces.
You wanted to execute the cout print after returning, which is impossible. Switch the order around.
So you should replace your fragment of code with this:
else {
cout << theRoot->data;
return theRoot->data;
}
Incidentally, don't let double semicolons (;;) stay in your code. It's harmless in most cases, but it's always bad style.
Here's a fixed and slightly cleaned-up version that works:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = 0;
rChildptr = 0;
}
};
private:
Node* root;
void Insert(T newData, Node** theRoot)
{
if (*theRoot == 0)
{
*theRoot = new Node(newData);
}
else if (newData < (*theRoot)->data)
Insert(newData, &((*theRoot)->lChildptr));
else
Insert(newData, &((*theRoot)->rChildptr));
}
void PrintTree(Node* theRoot)
{
if (theRoot != 0)
{
PrintTree(theRoot->lChildptr);
cout << theRoot->data << " " << endl;
PrintTree(theRoot->rChildptr);
}
}
T Largest(Node* theRoot)
{
if (root == 0)
{
throw "There is no tree";
}
if (theRoot->rChildptr != 0)
return Largest(theRoot->rChildptr);
else
return theRoot->data;
}
public:
BinaryTree()
{
root = 0;
}
void AddItem(T newData)
{
Insert(newData, &root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
cout << "The tree is empty. Trying to find the largest element." << endl;
try
{
cout << "Largest element: " << myBT->Largest() << endl;
}
catch (const char* e)
{
cout << "Exception caught: " << e << endl;
}
myBT->AddItem(15);
myBT->AddItem(2);
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(10);
cout << "Tree:" << endl;
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl;
}
Output:
The tree is empty. Trying to find the largest element.
Exception caught: There is no tree
Tree:
1
2
5
10
15
Largest element: 15