I am doing a project about search engine usinng binary tree.
I think there are a lot of problems. I tried so mush without any result
and I don't know how to call Btree in main, it gives me an error all the time.
I have a text file with int and string. It will be like this:
1925 John Baird transmits the first television signal
In this program I will search by the int year and give the information of what happend in that year.
1-information class
#include <iostream>
#include <string>
using
namespace std;
class information{
private:
int year;
string data;
public:
information(int year, string data);
string getData();
int getyear();
void setData(string dat);
void setYear(int yer);
};
2- BinNode class
#include "information.h"
#include <iostream>
// Binary tree node ADT
template <typename Elem> class BinNode {
public:
virtual ˜BinNode() {}
virtual void setEvent(const information&) = 0;
virtual BinNode* left() const = 0;
virtual void setLeft(BinNode*) = 0;
virtual BinNode* right() const = 0;
virtual void setRight(BinNode*) = 0;
virtual bool isLeaf() = 0;
};
3-BNode class
#include <iostream>
#include "BinNode.h"
#include "information.h"
using namespace std;
// Binary tree node implementation
template <typename Elem>
class BNode: public BinNode<Elem> {
private:
information Event;
BNode* lc;
BNode* rc;
public:
BNode() { lc=rc=NULL;}
BNode(information d, Bnode* l = NULL,
Bnode* r = NULL) {
info = d; lc = l; rc = r;
}
information getEvent(){
return information.getEvent;
}
information setEvent(information e) {
Event = e;
}
BNode* left() const {return lc;}
void setLeft(BNode* b) {lc = b;}
BNode* right() const {return rc;}
a
void setRight(BNode* b) {rc = b}
bool isLeaf() {
return (lc==NULL) && (rc==NULL);
}
};
4- BinaryTree class
#include <iostream>;
// Binary tree ADT
template <int> class BinaryTree {
public:
BinaryTree();
virtual bool search() =0;
virtual bool search() =0;
virtual void insert() =0;
virtual bool remove() = 0;
virtual void fillTree() = 0
};
5- BTree class
#include <iostream>
#include<fstream>
#include "BinaryTree.h"
#include "BNode.h"
#include "information.h"
using namespace std;
// Binary tree implementation
template <type Elem> class BTree: public BinaryTree<Elem> {
private:
BNode* root;
public:
BinaryTree() {root = NULL;}
void insert(information i){
BNode* current;
BNode* trailCurrent;
BNode* newNode;
newNode = new BNode;
newNode->Event= i;
newNode->lc=NULL; newNode->rc=NULL;
if (root == NULL)
root = newNode;
else{
current = root;
while(current!=NULL){
trailCurrent = current;
if (current->Event== i){
cout<< “No duplicate allowed”;return;}
else if (current->Event> key)
current = current->lc;
else current = current->rc;
}
if(trailCurrent->Event> i)
trailCurrent->lc = newNode;
else trailCurrent->rc = newNode;
}
}
bool search(int key){
Bnode* current;
bool found = false;
if (root == NULL)
cout << "Empty Tree";
else{
current = root;
while(current!= NULL && !found){
if (current->Event.getYear() == key)
found = true;
cout << "The IN FORMATION for " << key << " is " << curr->Event.getData() << endl;
else if (current->Event> key)
current = current->lc;
else current = current->rc;
}
}
}
bool remove(information i){
BNode* current;
BNode* newNode;
newNode = new BNode;
newNode->Event= i;
newNode->lc=NULL; newNode->rc=NULL;
current = root;
while(current!=NULL){
if (current->Event== i){
delete current;
}
}
}
};
6- main
#include <iostream>
#include "BTree.h"
#include "information.h"
#include <fstream>
#include<string>
using namespace std;
int main(){
BTree <> b;
int ch;
string data;
int key,key2;
int year;
ifstream file;
file.open("date.txt");
if(!file) {
cout<<" Error opening file. " << endl;
}
while(file >> year >> data)
{
year = file.get();
p.setYear(year);
cout << p.getyear() << " ";
getline ( file, data );
p.setData(data);
cout << p.getData() << endl;
b.insert(p);
}
file.close();
while(1)
{
cout<<" Binary Search Tree"<<endl;
cout<<" 0. Search by year"<<endl;
cout<<" 1. Search by tow year "<<endl;
cout<<" 2. Exit "<<endl;
cout<<" Enter your choice : ";
cin>>ch;
switch(ch)
{
case 0 : cout <<" Enter the year to search : "<<endl;
cin>>key;
b.search(key);
break;
case 1 : cout<<" Enter the first year: ";
cin>>key;
cout<<" Enter the socend year: ";
cin>>key2;
// b.search(key,key2);
break;
case 2 : return 0;
}
}
};
I can see a problem, The Btree class is reinitalizing the constructor to BinaryTree
It should be:
public:
//BinaryTree() {root = NULL;}
Btree() { }
The Derived class, by principle will call Base classes constructor.
Another one:
virtual bool search() =0;
is being declared twice.
Another one:
virtual void fillTree() = 0;
Requires you to define a fillTree function in your Btree(Derived) class. Or have it as an absolute virtual function in the Derived class, but then that means the class must not be initiated, and should Inherited by another Dervied class which defines the virtual function.
This link might help
Related
I have a linked list class that uses templates for both the Node class and the List class. I've done some debugging and come to the conclusion that in my Node class, the member functions cannot access the member data, but the constructors can. I would like to know how i can fix this!
#include <iostream>
#include <fstream>
#include <string>
#include "List.h"
using namespace std;
int main()
{
ifstream fileIn("data1.txt");
List<int> studentList;
if(fileIn.fail())
cout << "file did not open" << endl;
else
studentList.add(fileIn);
fileIn.close();
cin.get();
cin.ignore();
return 0;
}
//List.h
//ignore the commented methods, have yet to write them.
#ifndef LIST_H
#define LIST_H
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "Node.h"
using namespace std;
template <class NumType>
class List
{
int counter;
bool isEmpty();
const bool print(){
}
public:
Node<NumType> * head;
List()
{
this->head = NULL;
counter = 0;
}
~List()
{
}
//place in an order thart keeps the array in ascending order
void add(ifstream &);
/*
Node* location(Node *){
}
bool remove(const int){
}
bool clear(){
}
const void peek(const Node*){
}
//average of all test scores or just one students test scores?
float average(){
}
char grade(){
}
*/
};
#include "List.cpp"
#endif
//List.cpp
#include "List.h"
using namespace std;
template <class NumType>
bool List<NumType> :: isEmpty()
{
cout << "inside isEmpty" << endl;
return(head == NULL);
}
template <class NumType>
void List<NumType> :: add(ifstream & fin)
{ int dummyID;
NumType tests[3];
string dummyName;
while(fin >> dummyID)
{ fin.ignore();
getline(fin, dummyName);
for(int x = 0; x < 3; x++)
fin >> tests[x];
fin.ignore();
cout << dummyID << endl;
cout <<dummyName << endl;
for(int y = 0; y < 3; y++)
cout << tests[y] << " ";
if(isEmpty())
{
this->head = new Node<NumType>(NULL, tests, dummyID, dummyName);
counter++;cout << "inside" << endl;
}
else
{
Node<NumType> *newNode = new Node<NumType>(NULL, tests, dummyID, dummyName);
Node<NumType> *first = new Node<NumType>(NULL, tests, dummyID, dummyName);
Node<NumType> *second;
first = this->head;
second = this->head->getNext();
//create location() method to handle this!
for(int x = 0; x < counter; x++)
{
if(first->getID() > newNode->getID())
{
head = newNode;
counter++;
break;
}
else if(first->getID() < newNode->getID() && second->getID() > newNode->getID())
{
newNode->setNext(second);
first->setNext(newNode);
counter++;
break;
}
else if(second->getID() < newNode->getID() && second->getNext() == NULL)
{
second->setNext(newNode);
counter++;
break;
}
else
{
first = second;
second = second->getNext();
}
}
}
}
Node<NumType> * temp = head;
for(int x = 0; x <= counter; x++)
{
NumType *arr;
cout << temp->getID() << endl << temp->getName() << endl;
arr = temp->getAllScores();
for(int y = 0; y <3 ; y++)
cout << *(arr+y) << endl;
temp = temp->getNext();
}
}
//Node.h
#ifndef NODE_H
#define NODE_H
#include <cstdlib>
#include <iostream>
using namespace std;
template <class ItemType>
class Node
{
static const int SIZE = 3;
int ID;
ItemType scores[SIZE];
string name;
Node *next;
public:
Node()
{
this->scores[0] = 0;
this->scores[1] = 0;
this->scores[2] = 0;
this->name = "";
this->ID = 0;
this->next = NULL;
}
Node(Node * nPtr, ItemType tests[], int num, string n)
{
this->next = nPtr;
for(int z = 0; z < SIZE; z++)
this->scores[z] = tests[z];
this->ID = num;
this->name = n;
}
~Node(){}
void setNext( Node * );
string getName();
int getID();
ItemType* getAllScores();
Node* getNext();
};
#include "Node.cpp"
#endif
Node.cpp
#include "Node.h"
#include <string>
using namespace std;
template <class ItemType>
void Node<ItemType> :: setNext( Node * nextPtr)
{
cout << "inside setNext()" << endl;
this->next = nextPtr;
cout << "exited setNext()" << endl;
}
template <class ItemType>
string Node<ItemType> :: getName()
{
return (this->name);
}
template <class ItemType>
int Node<ItemType> :: getID()
{
return (this->ID);
}
template <class ItemType>
ItemType* Node<ItemType> :: getAllScores()
{
return (this->scores);
}
template <class ItemType>
Node<ItemType> * Node<ItemType> :: getNext()
{
return (this->next);
}
I think I found the error. The first time you run the add method head is set, but the second time you are trying to set the second value. You have this code
first = this->head;// this is the first element
second = this->head->getNext(); // this is null (hast been assign yet
then you go inside of a for loop, and in the first "else if" statement you have this:
else if(first->getID() < newNode->getID() && second->getID() > newNode->getID())
when you say second->getID() you are saying null->getID() causing you a segmentation fault.
I hope this fixes your problem. Good luck!
I'm trying to make program that reads from a file and adds to a binary tree, but when I try to compile I get an error:
"Error 1 'treePersons::display' : cannot convert parameter 1 from 'Node *' to 'Person *[]'"
The error appears in the call to display() in main()
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct Person{
int social;
int birthday;
string first;
string last;
string state;
double balance;
Person();
Person(int s, int b, string f, string l, string t, double a)
{
social = s;
birthday = b;
first = f;
last = l;
state = t;
balance = a;
}
};
struct Node{
Person data;
Node *left;
Node *right;
Node();
Node(Person x){
data = x;
left = NULL;
right = NULL;
}
};
class treePersons
{
protected:
public:
Node *root;
treePersons(){
root = NULL;
}
int fileName(Person *data[])
{
ifstream fin;
fin.open ("dbfile1.txt");
if (!fin.is_open())
cout << "File not found" << endl;
int i;
for(i = 0; i<100; i++)
while(fin.good())
{
fin >> data[i]->social >> data[i]->birthday >> data[i]->first >> data[i]->last >> data[i]->state >> data[i]->balance;
i++;
}
return i;
}
void add(Person *data[], Node*root)
{
int i = fileName(data);
if(root == NULL)
{
root = new Node();
}
for(int l = 0; l<i; l++)
{
if(data[i]->last == root->data.last)
{
if(data[i]->first != root->data.first)
{
if(data[i]->first < root->data.first)
{
add(data, root->left);
}
else if(data[i]->first > root->data.first)
{
add(data, root->right);
}
else if(data[i]->last == root->data.last && data[i]->first == root ->data.first)
{
cout << "already exists" << endl;
}
else if(data[i]->first < root->data.first)
{
add(data, root->left);
}
else if(data[i]->first > root->data.first)
{
add(data, root->right);
}
}
}
}
}
void printAlphabetically(Node *root)
{
if (root != NULL)
{
printAlphabetically(root->left);
cout << root->data.last << endl;
printAlphabetically(root->right);
}
return;
}
void display(Person *data[],Node *root)
{
add(data,root);
printAlphabetically(root);
};
};
struct State{
string state;
Person data;
State* left;
State * right;
State();
State(Person x)
{
data = x;
left = NULL;
right = NULL;
}
};
class treeState{
protected:
State *root;
public:
treeState()
{
root = NULL;
}
};
void main(){
treePersons T;
T.display(T.root->data,T.root);
}
It's very simple to see what's wrong with your code. You have the following:
treePersons T;
T.display(T.root->data, T.root);
Let's have a look at what a treePersons is:
class treePersons
{
Node *root;
...
};
It contains a single member: a Node. A Node is:
struct Node
{
Person data;
Node *left;
Node *right;
...
};
Your treePersons::display() function has the following signature:
void display(Person *data[], Node *root)
And you are passing a t.root->data (a Person) and t.root (a Node*)
The problem is you are attempting to pass a Person as a Person*[] which just isn't going to happen. There's no way to make that Person into a Person[], and you probably meant to make display take a Person* pointer, which will allow you pass a single Person or a container of Person: void display(Person* data, Node* root);
Of course, doing so will lead you down a big trail of problems as #R Sahu pointed out in the comments (most of your functions take a Person*[]. The solution here is to rethink what you are doing, and as #R Sahu suggests start much smaller and build up your program from there.
Consider also using std::vector when you need containers, and std::unique_ptr or std::shared_ptr where you require pointers (otherwise just use objects!). Also read (really read) the compiler output. It's telling you what the problem is, you just need to read.
I have created a linked list that each node holds a CarPart object. I know that the issue is that I am not properly de-referencing the pointer and it just displays the pointer and not the actual value... problem being is I have not been able to figure out how properly display the car part items to the console.
Per request I have removed any code that does not effect the outcome of what I am trying to do.
Main.cpp
#include "stdafx.h"
#include "List.h"
int main()
{
/*cout << new Node(new CarPart("Hello", "World", 99.00));*/
List partsList;
partsList.push_front(new CarPart("FL2016", "Oil Filter", 18.95));
partsList.push_front(new CarPart("RS12YC", "Spark Plug", 4.15));
partsList.push_front(new CarPart("D5941", "Digital Tire Guage", 12.15));
partsList.push_back(new CarPart("G19216", "Car Wash Solution", 8.15));
partsList.display();
cout << "now we are going to remove the first item in the list" << endl;
system("PAUSE");
partsList.pop_front();
partsList.display();
system("PAUSE");
cout << "now we are going to remove the LAST item from the list" << endl;
partsList.pop_back();
partsList.display();
system("PAUSE");
return 0;
}
List.h
#pragma once
#include "node.h"
class List
{
private:
int listSize;
Node* n;
Node* temp;
Node* head;
Node* tail;
public:
List();
void push_front(CarPart*);
void push_back(CarPart*);
void pop_front();
void pop_back();
void display();
~List();
};
List.cpp
#include "stdafx.h"
#include "List.h"
List::List()
{
}
void List::display()
{
Node* test = head;
for (int i = 0; i < listSize; i++) {
cout << test;
}
}
Node.h
#pragma once
#include "CarPart.h"
class Node
{
private:
CarPart* data;
Node* next;
Node* previous;
public:
Node();
CarPart* getData();
void setData(CarPart*);
void setNext(Node*);
void setPrevious(Node*);
Node* getPrevious();
Node* getNext();
void display();
~Node();
};
Node.cpp
#include "stdafx.h"
#include "Node.h"
Node::Node()
{
}
void Node::display()
{
cout << data;
}
CarPart.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class CarPart
{
private:
string partNumber;
string description;
double price;
public:
CarPart();
CarPart(string, string, double);
string getPartNumber();
string getDescription();
double getPrice();
void display();
~CarPart();
friend ostream& operator<<(ostream& os, CarPart* dt);
};
CarPart.cpp
#include "stdafx.h"
#include "CarPart.h"
CarPart::CarPart()
{
}
CarPart::CarPart(string n, string d, double p)
{
partNumber = n;
description = d;
price = p;
}
string CarPart::getPartNumber()
{
return partNumber;
}
string CarPart::getDescription()
{
return description;
}
double CarPart::getPrice()
{
return price;
}
ostream& operator<<(ostream& os, CarPart* dt)
{
os << dt->getPartNumber() << endl << dt->getDescription() << endl << dt->getPrice() << endl;
return os;
}
There are multiple problems with your code, but they all share the same root problem, so I'll just explain the first one, and after figuring out how to fix it you should be able to fix the rest of them by yourself:
void List::display()
{
Node* test = head;
for (int i = 0; i < listSize; i++) {
cout << test;
}
}
As you've observed, all this does is print the value of the pointer. Examining the contents of your header files, it appears that your class Node has a method called display().
You did now show the display() method, but given what I see in List::display(), it's reasonable to expect that Node::display()'s purpose would be similar, so you probably meant to do this, instead:
void List::display()
{
Node* test = head;
for (int i = 0; i < listSize; i++) {
test->display();
}
}
But this is not right, either. All this will accomplish is invoke your head Node's display() method over and over again. If your List has five Nodes, you'll get the contents of the first Node display()ed five times. You simply need to change this loop to walk through the link list, instead.
Now, your Node::display() method has the same problem as above, but now you should be able to fix it yourself.
I am having a bit of an issue with my derived classes and how they utilize the search function that they inherit from their parent class.
Here is my .h file
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
#define TABLESIZE 13
#ifndef HASH_H
#define HASH_H
namespace HTGroup
{
template<class T>
class HashTable
{
protected:
struct item {
T x;
item* next;
};
item* HT[TABLESIZE];
virtual int hash(T key) = 0;
virtual int collision(T key, int &value) = 0;
public:
HashTable();
virtual void printGrid();
void insert(T key);
void remove(T key);
void search(T key);
int indexItems(int index);
};
template<class T>
class DHT1 : public HashTable<T>
{
protected:
int hash(T key);
int collision(T key, int &value);
struct item {
T x;
item* next;
};
item* HT[TABLESIZE];
public:
DHT1();
void printGrid();
};
template<class T>
class DHT2 : public HashTable<T>
{
protected:
int hash(T key);
int collision(T key, int &value);
struct item {
T x;
item* next;
};
item* HT[TABLESIZE];
public:
DHT2();
void printGrid();
};
}
#endif
Here is what I have implemented for the search function:
template<class T>
void HashTable<T>::search(T key)
{
int index = hash(key);
bool foundKey = false;
string item;
item* temp = HT[index];
while(temp != NULL)
{
if(temp->x == key)
{
foundKey = true;
item = temp->x;
}
temp = temp->next;
}
if(foundKey == true)
{
cout << "Item was found." << endl;
}
else
{
cout << "Item was not found." << endl;
}
}
And this is how I am calling the function in my main:
hashy1.search(item);
I am getting an error from the compiler with this line from my search implementation:
item* temp = HT[index];
Giving me this error:
[Error] 'temp' was not declared in this scope
From my understanding whenever an object of a derived class is calling the search function it is getting confused with whether or not the pointer created is of the parent class or the derived class.
The weird thing though is that it has let me create other pointers in my remove function without any issues and it works fine:
template<class T>
void HashTable<T>::remove(T key)
{
int index = hash(key);
item* delPtr; //Where I am allowed to create pointers with
item* P1; //no issues
item* P2;
if(HT[index]->x == "")
{
cout << key << " was not found in the hash table" << endl;
}
else if ( HT[index]->x == key && HT[index]->next == NULL)
{
HT[index]->x = "";
cout << key << " was removed from the hash table" << endl;
}
else if(HT[index]->x == key)
{
delPtr = HT[index];
HT[index] = HT[index]->next;
delete delPtr;
cout << key << " was removed from the hash table" << endl;
}
else
{
P1 = HT[index]->next;
P2 = HT[index];
while(P1 != NULL && P1->x != key)
{
P2 = P1;
P1 = P1->next;
}
if(P1 == NULL)
{
cout << key << " was not found in the hash table" << endl;
}
else
{
delPtr = P1;
P1 = P1->next;
P2->next = P1;
delete delPtr;
cout << key << " was removed from the hash table" << endl;
}
}
}
I've tried creating the pointer in the .h file like this:
template<class T>
class DHT1 : public HashTable<T>
{
protected:
int hash(T key);
int collision(T key, int &value);
struct item {
T x;
item* next;
item* temp; // Added declaration
};
item* HT[TABLESIZE];
public:
DHT1();
void printGrid();
};
But that still gives me declaration issues
Are there different methods I should be using when implementing my search function such as any extra parameters in the function call? Or maybe I am just not getting the logic down right?
Thank you for any responses!
You declared item as a std::string, and then you use item in the same scope as a type.
string item; // <-- declaring as string
item* temp = HT[index]; // <-- Compiler doesn't know what to do with this line except to give an error.
The simplest solution is to name your std::string variable something else other than item.
This question already has an answer here:
C++: Pointer vs Pointer of Pointer to insert a node in a Binary Tree
(1 answer)
Closed 7 years ago.
#include <fstream>
#include <vector>
#include <iterator>
#include <iostream>
#include <string>
using namespace std;
ifstream fin("1.inp");
class TreeNode {
private:
friend class Tree;
int Keyvalue;
string Namevalue;
TreeNode *LeftChild;
TreeNode *RightChild;
TreeNode() { LeftChild = RightChild = 0; };
TreeNode(int _Keyvalue, string _Namevalue, TreeNode *Lefty, TreeNode *Righty) {
Keyvalue = _Keyvalue;
Namevalue = _Namevalue;
LeftChild = Lefty;
RightChild = Righty;
}
};
class Tree {
private:
TreeNode *root;
void insert_to_tree(TreeNode *, int, string);
void show_tree(TreeNode *);
public:
Tree() { root = 0; }
void insert_to_tree(int, string);
void delete_from_tree(int);
void show_tree();
void setup();
};
void Tree::insert_to_tree(int _Keyvalue, string _Namevalue){
insert_to_tree(root, _Keyvalue, _Namevalue);
}
//this is problem.
void Tree::insert_to_tree(TreeNode *CurrentNode, int _Keyvalue, string _Namevalue){
if (CurrentNode == 0)
CurrentNode = new TreeNode(_Keyvalue, _Namevalue, 0, 0);
else{
if (CurrentNode->Keyvalue < _Keyvalue)
insert_to_tree(CurrentNode->RightChild, _Keyvalue, _Namevalue);
else if (CurrentNode->Keyvalue == _Keyvalue)
CurrentNode->Namevalue = _Namevalue;
else
insert_to_tree(CurrentNode->LeftChild, _Keyvalue, _Namevalue);
}
}
void Tree::delete_from_tree(int _Keyvalue){
}
void Tree::show_tree(){
show_tree(root);
}
void Tree::show_tree(TreeNode *CurrentNode){
if (CurrentNode){
if (CurrentNode->LeftChild == 0 && CurrentNode->RightChild == 0){
cout << CurrentNode->Namevalue;
}
else{
show_tree(CurrentNode->LeftChild);
show_tree(CurrentNode->RightChild);
}
}
}
void get_command(Tree &_MyTree){
int Num_of_command;
string command;
fin >> Num_of_command;
for (int i = 0; i < Num_of_command; i++){
fin >> command;
int Keyvalue; string Namevalue;
if (command == "ins"){
fin >> Keyvalue >> Namevalue;
_MyTree.insert_to_tree(Keyvalue, Namevalue);
}
else if (command == "del"){
fin >> Keyvalue;
_MyTree.delete_from_tree(Keyvalue);
}
else if (command == "leaves")
_MyTree.show_tree();
}
}
int main(){
Tree MyTree;
get_command(MyTree);
}
When I call the function
void Tree::insert_to_tree(int _Keyvalue, string _Namevalue){
insert_to_tree(root, _Keyvalue, _Namevalue); }
root isn't changed by my function. After the function
void Tree::insert_to_tree(TreeNode *CurrentNode, int _Keyvalue, string _Namevalue)
root is always 0.
You are passing root by value - which means, your function sees a copy of root. Whatever it does to it, doesn't affect the original.
Consider the following simple example:
#include <iostream>
void foo(int x) {
x = 10;
}
int main() {
int k = 42;
foo(k);
std::cout << "k is now " << k << "\n";
return 0;
}
If you run this code, you will see that k remains unchanged and is still printed as 42. This is because foo() modified the copy of k, and this did not touch original k.
You create a new TreeNode but you never insert it into the tree or return the created TreeNode anywhere.
You probably mean to pass the CurrentNode by reference (TreeNode *& CurrentNode) which means that any changes made to it inside the functions will be seen outside the functions.