help with insert on first BST - c++

EDIT there a small thing that I am missing!! the error is still there
So I am attempting to learn how to code my first BST, and it is hard.... I am already having trouble with just a few lines of codes. the problem is in the insert, but I have included everything so that I could get some feedback on my style/other errors. I was suggested to use a pointer to pointer implementation, but we havent learned it yet, so I dont feel comfort/know how to code it yet. the
error is
[trinhc#cs1 Assignment_3]$ g++ movieList.cpp -o a.out
/tmp/ccLw6nsv.o: In function `main':
movieList.cpp:(.text+0x7a): undefined reference to `Tree::Tree()'
movieList.cpp:(.text+0xa7): undefined reference to `Tree::insert(int, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: ld returned 1 exit status
the tree.h file
#ifndef TREE_H
#define TREE_H
#include <string>
#include <iostream>
using namespace std;
class Tree
{
public:
Tree();
bool insert(int k, string s);
private:
struct Node
{
int key;
string data;
Node *left;
Node *right;
};
Node* root;
bool insert(Node*& root, int k, string s);
};
#endif
tree.cpp
#include <iostream>
#include "tree.h"
#include <stack>
#include <queue>
#include <string>
using namespace std;
Tree::Tree()
{
root = NULL;
}
bool Tree::insert(int k, string s)
{
return insert(root, k, s);
}
bool Tree::insert(Node*& current_root, int k, string s)
{
if(root == NULL){
current_root = new Node;
current_root->key = k;
current_root->data = s;
current_root->left = NULL;
current_root->right = NULL;
return true;
}
else if (current_root->key == k)
return false;
else if (current_root->key > k)
insert(current_root->left, k, s);
else
insert (current_root->right,k, s);
}
movieList.cpp
#include <iostream>
#include <stack>
#include <queue>
#include <string>
#include "tree.h"
using namespace std;
int main()
{
Tree test;
test.insert(100, "blah");
return 0;
}

Tree test(); is not how define an object of class Test, This acutally declare function named test which returns Tree.
try
Tree test;
test.instert(100, "blah");
return 0;

I copied some of your code and this is working fine for me:
main:
#include <iostream>
#include <stack>
#include <queue>
#include <string>
#include "tree.h"
int main()
{
Tree test;
test.insert(100, "blah");
test.insert(50, "fifty");
test.insert(110, "one hundred ten");
return 0;
}
Insert function:
bool Tree::insert(Node*& currentRoot, int k, string s)
{
if(currentRoot == NULL){
currentRoot = new Node;
currentRoot->key = k;
currentRoot->data = s;
currentRoot->left = NULL;
currentRoot->right = NULL;
return true;
}
else if (currentRoot->key == k)
return false;
else if (currentRoot->key > k)
insert(currentRoot->left, k, s);
else
insert (currentRoot->right,k, s);
}
Other than that you have syntax errors all over the place. I also changed the name because as someone pointed out there was a bit of a naming problem. CurrentRoot makes sense because you are passing it the root of the left or right subtree on every recursion.

Couple of points:
You need to change the name of your member variable root to something else– I'd recommend m_root, or my_root, or tree_root, or something of those sorts. Right now you've got a little bit of a namespace clash in any function where you include root as an argument. This will also let you keep track of which root you're referring to.
bool Tree::insert(Node*& root, int k, string s)
{
if(root == NULL){
root = new Node;
root->key = k;
root->data = s;
root->left = NULL;
root->right = NULL;
return true;
} else
if (root == k) //Comparison between pointer and number.
return false;
else
if (root->key > k)
insert(root->left, k, s);
else
insert (root->right,k, s);
}
You need to change root on the commented line to root->key.
Other than that, it looks like it'll work.
EDIT: Also, what the other guy said. You declare an object as
TYPE name ()
if you are calling the default constructor (), so your code in your main function should be
Tree test;
test.insert(...)

Shouldn't you add tree.cpp to your build command?
[trinhc#cs1 Assignment_3]$ g++
movieList.cpp -o a.out
Would become
[trinhc#cs1 Assignment_3]$ g++
tree.cpp movieList.cpp -o a.out

Related

Cursor not moving in tree insert function, found in provided header file that has constructor and class definition. How can I move the cursor forward?

The assignment requires that I write the code for an Insert, Print and Find functions in the already provided tree header file. It's a very simple search tree for ints. Here is the header file:
#include <map>
#include <iostream>
class Tree {
Tree *left;
Tree *right;
int node;
static std::map<int, Tree*> allNodes;
public:
Tree(int n, Tree *l=0, Tree *r=0) : left(l), right(r), node(n) {
allNodes[n] = this;
}
int GetNode() { return node; }
void Insert(Tree *newnode) {
// insert code to Insert newnode into tree pointed to by this... return the tree
// My own code // cout<<this->node;
if( newnode->node == this->node ){}
// skip dup
//Everything after is also my code
else if (newnode->node < this->node){
left = newnode;
cout<<"left"<<left->node<<endl;
}
else if (newnode->node > this->node){
right = newnode;
cout<<"right"<<right->node<<endl;
}
}
Here is the code that implements it(I wrote the code at the very bottom):
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include "trav.h"
std::map<int, Tree*> Tree::allNodes;
// trav print
// trav find X
int
main(int argc, char *argv[])
{
if( argc < 2 )
return 0;
string cmd(argv[1]);
// READ IN THE INTEGERS
vector<int> ids;
int input;
while( cin >> input ) {
ids.push_back( input );
}
// MAKE NODES FROM THE INTEGERS
vector<Tree*> nodes;
for( int id: ids ) {
nodes.push_back( new Tree(id) );
}
if( ids.size() == 0 )
return -1;
// PUT NODES INTO A TREE USING Insert
Tree *theTree = nodes[0];
if( theTree == nullptr )
return -1;
for( auto n : nodes ) {
//My code// theTree->Insert(n);
}
// PRINT TREE
if( cmd == "print" ) {
theTree->Print();
}
/*if (cmd == "find") {
string no = argv[2];
int num = atoi(no);
int result = theTree-> find(num);
if(result!=0)
cout<<num<<endl;
else
cout<<"-1"<<endl;
}*/
return 0;
}
Here is my output:
3232left8
32left3
32left5
32left9
32right40
32right100
32right632
32left1
32left9
32left9
32left3
32left2
32right64
32right43
2
43
32
Those last 3 numbers are from my print function.
The cursor doesn't appear to be moving forward. I've tried setting this=left, which returns an error. What can I do? And I'm not sure how to use the allNodes. Do I implement it in the insert function?

Implementing a Suffix Trie using OOP/C++

I am trying to implement a suffix trie in C++ for a programming assignment. Now I think I have the right idea, but I keep getting a segmentation fault and I haven't been able to find what's causing it.
For this assignment, we are encouraged to use VIM/some other basic text editor, and compile programs from the console. Nevertheless, I've downloaded CLion to try and debug the code so I can find the error.
Now when running in CLion I get the message
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Trying to run the debugger gives the message
Error during pretty printers setup:
Undefined info command: "pretty-printer". Try "help info".
Some features and performance optimizations will not be available.
I'm new to CLion and I'm not sure what to do about this (The only JetBrains IDE I use is Pycharm). Can you help me resolve this?
Now the program itself consists of three classes, Trie, Edge and Node, whose implementations can be seen below. The main idea behind the implementation of the Trie is in the constructor of Trie.cpp.
The code is detailed in full below. I appreciate any help.
Main.cpp
#include <iostream>
using namespace std;
#include "Trie.hpp"
int main(){
string s = "Stef";
Trie trie(s);
return 0;
}
Trie.hpp
#ifndef TRIE_HPP
#define TRIE_HPP
#include <string>
#include "Node.hpp"
#include "Edge.hpp"
using namespace std;
class Trie{
private:
string T;
vector<Node> nodes;
void addWord(Node*, string);
public:
Trie(string);
};
#endif
Trie.cpp
#include <iostream>
#include <cstring>
#include "Trie.hpp"
using namespace std;
Trie::Trie(string T){
T += "#"; //terminating character
this->T = T;
vector<string> suffix; //array of suffixes
for(unsigned int i = 0; i < T.length(); i++)
suffix.push_back(T.substr(i, T.length()-i));
//Create the Root, and start from it
nodes.push_back(Node("")); //root has blank label
Node* currentNode = &nodes[0];
//While there are words in the array of suffixes
while(!suffix.empty()){
//If the character under consideration already has an edge, then this will be its index. Otherwise, it's -1.
int edgeIndex = currentNode->childLoc(suffix[0].at(0));
//If there is no such edge, add the rest of the word
if(edgeIndex == -1){
addWord(currentNode, suffix[0]); //add rest of word
suffix.erase(suffix.begin()); //erase the suffix from the suffix array
break; //break from the for loop
}
//if there is
else{
currentNode = (currentNode->getEdge(edgeIndex))->getTo(); //current Node is the next Node
suffix[0] = suffix[0].substr(1, suffix[0].length()); //remove first character
}
}
}
//This function adds the rest of a word
void Trie::addWord(Node* parent, string word){
for(unsigned int i = 0; i < word.length(); i++){ //For each remaining letter
nodes.push_back(Node(parent->getLabel()+word.at(i))); //Add a node with label of parent + label of edge
Edge e(word.at(i), parent, &nodes.back()); //Create an edge joining the parent to the node we just added
parent->addEdge(e); //Join the two with this edge
}
}
Node.hpp
#ifndef NODE_HPP
#define NODE_HPP
#include <string>
#include <vector>
#include "Edge.hpp"
using namespace std;
class Node{
private:
string label;
vector<Edge> outgoing_edges;
public:
Node();
Node(string);
string getLabel();
int childLoc(char);
void addEdge(Edge);
Edge* getEdge(int);
};
#endif
Node.cpp
#include "Node.hpp"
using namespace std;
Node::Node(){
}
Node::Node(string label){
this->label = label;
}
string Node::getLabel(){
return label;
}
//This function returns the edge matching the given label, returning -1 if there is no such edge.
int Node::childLoc(char label){
int loc = -1;
for(unsigned int i = 0; i < outgoing_edges.size(); i++)
if(outgoing_edges[i].getLabel() == label)
loc = i;
return loc;
}
void Node::addEdge(Edge e){
outgoing_edges.push_back(e);
}
Edge* Node::getEdge(int n){
return &outgoing_edges[n];
}
Edge.hpp
#ifndef EDGE_HPP
#define EDGE_HPP
#include <string>
using namespace std;
class Node; //Forward definition
class Edge{
private:
char label;
Node* from;
Node* to;
public:
Edge(char, Node*, Node*);
char getLabel();
Node* getTo();
Node* getFrom();
};
#endif
Edge.cpp
#include "Edge.hpp"
using namespace std;
Edge::Edge(char label, Node* from, Node* to){
this->label = label;
this->from = from;
this->to = to;
}
char Edge::getLabel(){
return label;
}
Node* Edge::getFrom(){
return from;
}
Node* Edge::getTo(){
return to;
}
&nodes[0];, &nodes.back() - you're storing pointers into a vector for later use, and these become invalid when the vector's underlying storage is relocated as you add elements to it.
Read about pointers in general, and dynamic allocation in particular, in your favourite C++ book.
If you don't yet have a favourite C++ book, pick one from this list.

error: no matching function for call to "Queue::Queue()"

So I am trying to call a function in my main.cpp file but I get "error: no matching function for call to 'Queue::Queue()."
Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
class Queue
{
public:
Queue(int);
~Queue();
//circular queue methods
void enqueue(std::string);
std::string dequeue(); //should send through network, call transmit msg
void printQueue();
bool queueIsFull(); //send when full
bool queueIsEmpty(); //send when empty
protected:
private:
int queueSize;
int queueHead;
int queueTail;
int queueCount;
std::string *arrayQueue;
};
#endif // QUEUE_H
Queue.cpp
#include "Queue.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
Queue::Queue(int qs)
{
queueSize = qs;
arrayQueue = new string[queueSize];
queueHead = 0;
queueTail = 0;
}
Queue::~Queue()
{
delete[] arrayQueue;
}
void Queue::enqueue(string word)
{
for (int i=0;i<10;i++)
{
arrayQueue[i] = word;
}
}
void Queue::printQueue()
{
for(int j=0;j<10;j++)
{
cout<<arrayQueue[j]<<endl;
}
}
main.cpp
#include <iostream>
#include "Queue.h"
using namespace std;
int main()
{
int userChoice;
Queue q;
while(2==2)
{
cout<<"======Main Menu======"<<endl;
cout<<"1. Enqueue word"<<endl;
cout<<"2. Dequeue word"<<endl;
cout<<"3. Print queue"<<endl;
cout<<"4. Enqueue sentence"<<endl;
cout<<"5. Quit"<<endl;
cin>>userChoice;
if (userChoice == 1)
{
string enqueueWord;
cout<<"word: ";
cin>>enqueueWord;
enqueue(enqueueWord);
}
if (userChoice == 2)
{
}
if (userChoice == 3)
{
}
if (userChoice == 4)
{
}
if (userChoice == 5)
{
}
}
return 0;
}
So to call the function from the header file I did "Queue q;" at the beginning of the int main() and then when I needed to call the function I did "q.enqueue(enqueueWord)." I also tried just doing "Queue::enqueue(enqueueWord), but that also didn't work and I get a different error. I feel like this is an easy fix but I just can't figure it out. Thanks for the help and feel free to ask me to clarify anything.
Queue q;
attempts to call the default constructor Queue::Queue. However, this constructor has been removed automatically since you explicitly declare a constructor, namely Queue::Queue(int), on your own.
Pass an appropriate argument to q when initialized, like
Queue q1(42); // pre-C++11 syntax
Queue q{42}; // available since C++11
(Note: 42 is only an exemplary value here.)
You could also use default arguments to keep the definition as-is and initialize the object with a default value.
Notes:
Why while(2==2)? while (true) is the common way.

Using class object in different cpp file

I was starting to learn to use class object in different .cpp file..
What I did:
Created a class of node in one file and saved it with node.h
Created another file with name node_pair.cpp and included node.h
Created a function named pair() and called it from main()
Now, I want to ask two things:
I am getting error: reference to ‘pair’ is ambiguous
Here is the code for node.h file
#include "iostream"
#include"stdlib"
using namespace std;
class node
{
int data;
public:
node *next;
int insert(node*);
node* create();
int display(node *);
} *start = NULL, *front, *ptr, n;
int node::insert(node* np)
{
if (start == NULL)
{
start = np;
front = np;
}
else
{
front->next = np;
front = np;
}
return 0;
}
node* node::create()
{
node *np;
np = (node*)malloc(sizeof(node)) ;
cin >> np->data;
np->next = NULL;
return np;
}
int node::display(node* np)
{
while (np != NULL)
{
cout << np->data;
np = np->next;
}
return 0;
}
int main_node()
{
int ch;
cout << "enter the size of the link list:";
cin >> ch;
while (ch--)
{
ptr = n.create();
n.insert(ptr);
}
n.display(start);
cout << "\n";
return 0;
}
and here is the code for node_pair.cpp
#include"iostream"
#include"node.h"
using namespace std;
node obj;
int pair()
{
node* one, *two, *save;
one = start;
two = start->next;
while (two != NULL)
{
save = two->next;
two->next = one;
one->next = save;
}
}
int main()
{
main_node();
pair();
obj.display(start);
return 0;
}
What should I do to resolve this error
And now the second problem
2. I want to keep node* next pointer to be private in node class but if I do so then I will not get access for it in pair() function.
Please answer, thanks in advance.
Some tips:
Your function pair clashes with std::pair.
Don't use using namespace std;. It's a bad practice and creates errors like this.
Mixing node.js and C++ is an advanced topic. If you just begun to learn OOP, I recommend that you stick to pure C++.
You have a name collision with your pair() and std::pair.
Best practice is to avoid using the entire namespace std -- just use what you need. For example, if you only need std::cin you can use using std::cin; to add it to the global namespace but not std::pair. You can also replace all instances of cin with std::cin instead.
If you really want to use the entire namespace std you can also create your own namespace to put your code in -- in particular, you'd need to put your pair() in this new namespace. You do it like this:
namespace mynamespace {
int pair() {
// ...
}
// ... other code in mynamespace
} // end mynamespace

Struct defined in header and included in two source codes is only defined in one

I have a struct defined in a header file with three other files that #include that header file. One is another header(queue.h) file that defines a very basic hash table and the other two are source codes where one is defining the functions from the hash table header(queue.cpp) and the other contains main(p2.cpp).
The problem that I'm having is that the struct seems to work fine in p2.cpp but in queue.h the compiler is telling me that the struct is undefined.
Here is p2.h containing the struct definition.
#ifndef __P2_H__
#define __P2_H__
#define xCoor 0
#define yCoor 1
#include <iostream>
#include <string>
#include "queue.h"
#include "dlist.h" //linked list which I know works and is not the problem
using namespace std;
struct spot {
float key[2];
string name, category;
};
#endif /* __P2_H__ */
I have queue.h included in this header so that I only have to include p2.h in p2.cpp.
Here is p2.cpp
#include <iostream>
#include <string>
#include <iomanip>
#include "p2.h"
using namespace std;
int main () {
cout << fixed;
cout << setprecision (4);
Queue hashTable;
spot *spot1 = new spot;
spot1->key[xCoor] = 42.2893;
spot1->key[yCoor] = -83.7391;
spot1->name = "NorthsideGrill";
spot1->category = "restaurant";
hashTable.insert(spot1);
Dlist<spot> test = hashTable.find(42.2893, -83.7391);
while (!test.isEmpty()) {
spot *temp = test.removeFront();
cout << temp->key[xCoor] << " " << temp->key[yCoor] << " " << temp->name << " " << temp->category << endl;
delete temp;
}
return 0;
}
Places and item in the hash table and takes it back out.
Here is queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <iostream>
#include <string>
#include "dlist.h"
#include "p2.h"
using namespace std;
class Queue {
// OVERVIEW: contains a dynamic array of spaces.
public:
// Operational methods
bool isEmpty();
// EFFECTS: returns true if list is empy, false otherwise
void insert(spot *o);
// MODIFIES this
// EFFECTS inserts o into the array
Dlist<spot> find(float X, float Y);
// Maintenance methods
Queue(); // ctor
~Queue(); // dtor
private:
// A private type
int numInserted;
int maxElts;
Dlist <spot>** queue;
// Utility methods
//Increases the size of the queue.
void makeLarger();
int hashFunc(float X, float Y, int modNum);
};
#endif /* __QUEUE_H__ */
Here is queue.cpp
#include <iostream>
#include <string>
#include <cstdlib>
#include "queue.h"
using namespace std;
bool Queue::isEmpty() {
return !numInserted;
}
void Queue::insert(spot *o) {
if (numInserted >= maxElts) {
makeLarger();
}
int index = hashFunc(o->key[xCoor], o->key[yCoor], maxElts);
queue[index] -> insertFront(o);
}
Queue::Queue() {
numInserted = 0;
maxElts = 1000;
queue = new Dlist<spot>*[maxElts];
for (int i = 0; i < maxElts; i++) {
queue[i] = new Dlist<spot>;
}
}
Queue::~Queue() {
for (int i = 0; i < maxElts; i++) {
delete queue[i];
}
delete[] queue;
}
void Queue::makeLarger() {
Dlist <spot>** temp = queue;
queue = new Dlist <spot>*[maxElts*2];
for (int i = 0; i < maxElts*2; i++) {
queue[i] = new Dlist<spot>;
}
for (int i = 0; i < maxElts; i++) {
while (!temp[i] -> isEmpty()) {
spot *spotTemp = temp[i] -> removeFront();
int index = hashFunc(spotTemp->key[xCoor], spotTemp->key[yCoor], maxElts*2);
queue[index] -> insertFront(spotTemp);
}
}
for (int i = 0; i < maxElts; i++) {
delete temp[i];
}
delete[] temp;
maxElts *= 2;
}
int Queue::hashFunc(float X, float Y, int modNum) {
return ((int)(10000*X) + (int)(10000*Y))%modNum;
}
Dlist<spot> Queue::find(float X, float Y) {
Dlist<spot> result;
Dlist<spot> *temp = new Dlist<spot>;
int index = hashFunc(X, Y, maxElts);
while (!queue[index] -> isEmpty()) {
spot *curSpot = queue[index] -> removeFront();
if ((curSpot->key[xCoor] == X) && (curSpot->key[yCoor] == Y)) {
result.insertFront(new spot(*curSpot));
}
temp -> insertFront(curSpot);
}
delete queue[index];
queue[index] = temp;
return result;
}
I believe that the problem is in my queue.h file because it's where I get all of the errors like "spot has not been declared". Every time spot appears in queue.h I have at least one error. I searched around for anything like this but all I could find was people trying to share one instance of a struct across multiple source files, or the obvious question of putting a struct in a header and including that header across multiple source files(which is what I'm doing but my problem seems to be a rather unique one).
You are including queue.h within the header that actually defines spot, so by the point the file is actually included spot has not been defined yet.
For your scope guards, note that identifiers starting with a double underscore are reserved by the implementation, don't use them.
And this is a poor choice even in plain C:
#define xCoor 0
#define yCoor 1
use this instead:
enum {
xCoor = 0
, yCoor = 1
};
Ok first never ever using "using" clauses in header files (it destroys the purposes of namespaces)
2nd provide a complete example that fails to compile
In addition to what others have said, you also have a circular reference error, which can also lead to similar undefined symbol errors. You have queue.h include p2.h, which includes queue.h.