I have made a C++ program for a binary tree. But the terminal is not asking the statement for inputting the direction for where the elements are to be placed.
Also when I replace the statement from " node *temp = new node " to "node *temp=NULL" the program stops working .
#include <iostream>
#include <cstring>
using namespace std;
class node {
int data;
node * left;
node * right;
public:
node * level_order(node * first);
node * create_bt(node * first);
void display(node * first);
};
//node *first=NULL;
node * node::create_bt(node * first) {
node * temp = new node;
int ele;
//char dir;
cout << "\n Enter data ";
cin >> ele;
temp->data = ele;
temp->left = NULL;
temp->right = NULL;
if (first == NULL) {
temp = first;
return first;
} else {
char dir[20];
cout << "\n Enter the direction ";
cin >> dir;
node * cur = first;
int j = 0;
while (dir[j] != '\0') {
if (dir[j] == 'l') {
cur = cur->left;
}
if (dir[j] == 'r') {
cur = cur->right;
}
j++;
}
cur = temp;
return first;
}
}
void node::display(node * first) {
if (first == NULL)
return;
cout << "\n " << first->data;
display(first->left);
display(first->right);
}
int main() {
int n;
node s;
node * first = NULL;
cout << "\n No of elements ";
cin >> n;
for (int i = 0; i < n; i++) {
first = s.create_bt(first);
}
s.display(first);
return 0;
}
first=s.create_bt(first); does not changes state, from NULL to 'l' or 'r'. You have to change that.
node*node::create_bt(node *first)
{
node *temp=new node;
int ele;
//char dir;
cout<<"\n Enter data ";
cin>>ele;
temp->data=ele;
temp->left=NULL;
temp->right=NULL;
char dir[20];
cout<<"\n Enter the direction ";
cin>>dir;
if(first==NULL)
{
temp=first;
return first;
}
else
{
node*cur=first;
int j=0;
while(dir[j]!='\0')
{
if(dir[j]=='l')
{
cur=cur->left;
}
if(dir[j]=='r')
{
cur=cur->right;
}
j++;
}
cur=temp;
return first;
}
}
I believe you re looking something like this. This is a basic binary tree, i had to make a basic one in order to understand how it works and how it chooses left and right. I make a class inside a class, in order to have access to my data members (node class, int data, *left , *right) and have them at the same time protected, all-in-one. As you can see "newnode" just creates a node and NULL s the pointers. Thats it. "Find" searches and finds a node with a current key, and returns it when exits. All the rest, i guess, you can understand them, as they are prety much the same with your code. The only thing you have to do is to define, when you want to direct the node you want. REMINDER: You have to find a way to utilize it, so the leafs will not end far-left or far-right.("Enter the direction"). I hope i helped you understand.
#include <iostream>
#include <conio.h>
using namespace std;
class mybTree {
class node {
public:
int data;
node * left;
node *right;
};
node *root;
node *newnode(int num){
node *newnode1;
newnode1 = new (nothrow) node;
newnode1->data = num;
newnode1->left = NULL;
newnode1->right = NULL;
return newnode1;
}
public:
node *find (int key) {
node *current;
current = root;
while (current->data !=key){
if (key<current->data){
current = current->left;
} else {
current = current->right;
}
if (current == NULL){
return NULL;
}
}
return NULL;
}
void display (node *ptr);
void display_tree();
bool insert(int num);
void post_order_delete(node *ptr);
mybTree();
~mybTree();
};
int main(){
char ch = ' ';
int a;
mybTree mybTree1;
while (ch !='0'){
cout << "0->Exit"<<endl<< "1-> add"<<endl<< "2-> find" <<endl<<"3-> Show me the tree\n";
ch = getch();
switch (ch) {
case '0':
break;
case '1':
cout << "number";
cin >> a;
if (!mybTree1.insert(a)){
cout << "Not enough memory" << endl;
}
break;
case '2' :
cout << "Number:" ;
cin >> a;
if (mybTree1.find(a)!=NULL) {
cout << "Found" << endl;
} else {
cout << "Not existed" << endl;
}
break;
case '3':
mybTree1.display_tree();
cout<<endl;
break;
default:
cout << "Wrong Message";
break;
}
}
return 0;
}
void mybTree::display(node *ptr) {
if (ptr == NULL){
return;
}
display(ptr->left);
cout << ptr->data<<endl;
display(ptr->right);
}
void mybTree::display_tree() {
//Displays the Tree
display(root);
}
bool mybTree::insert(int num) {
//It inserts a node. Desides left or right.
node *next,*current,*ptr;
int isleft;
next = current = root;
ptr = newnode(num);
if (ptr == NULL) {
return false;
}
if (root == NULL) {
root = ptr;
return true;
}
while (1){
if (num < current->data){
next = current->left;
isleft = 1;
} else {
next = current->right;
isleft = 0;
}
if (next == NULL){
if (isleft){
current->left = ptr;
} else {
current->right = ptr;
}
return true;
}
current=next;
}
return false;
}
void mybTree::post_order_delete(node *ptr) {
//deletes the node. Usefull for destructor
if (ptr == NULL){
return;
}
post_order_delete(ptr->left);
post_order_delete(ptr->right);
cout << ptr->data;
delete ptr;
}
mybTree::mybTree() {
//Constructor
root = NULL;
}
mybTree::~mybTree() {
//Destructor
post_order_delete(root);
root = NULL;
}
Related
I am trying to make a tree data structure with c++. Originally I tested with int data, it was going fine. However, when I try to use a string data type, it keeps showing an unhandled exception. It said read access violation, this was 0x5D. I don't know what is causing the error. The complete same code only changing int to string causes the violation.
Main:
#include <bits/stdc++.h>
#include "Tree.h"
using namespace std;
int main()
{
Tree A;
int choice; bool isCre=0;
cout << "Input choice : ";
while (cin >> choice) {
switch (choice)
{
case 1:
if (!isCre) {
A.create_tree(); isCre = 1;
break;
}
else {
A.add_tree();
break;
}
case 2:
A.delete_tree(); break;
case 3:
A.modify_tree(); break;
case 4:
A.display_tree(); break;
}
cout << "Input choice : ";
}
}
Header file:
#ifndef TREE_H
#define TREE_H
#include <bits/stdc++.h>
using namespace std;
class Tree
{
private:
struct Tre
{
Tre* parent; Tre* right; Tre* left;
string data;
Tre(Tre* parent, string data)
{
this->parent = parent;
this->data = data;
left = right = NULL;
}
};
Tre* root;
Tre* create(Tre*& root, string data)
{
Tre* p;
p = new Tre(NULL, data);
root = p;
return root;
}
void dis(Tre* node)
{
if (node == NULL)
return;
cout << node->data << endl;
dis(node->left);
dis(node->right);
}
Tre* search(Tre* node, string data)
{
if (node == NULL)
return NULL;
if (node != NULL && node->data == data)
return node;
/* then recur on left subtree */
Tre* p = search(node->left, data);
// node found, no need to look further
if (p != NULL && p->data == data) return p;
/* node is not found in left,
so recur on right subtree */
Tre* q = search(node->right, data);
if (q != NULL && q->data == data) return q;
}
Tre* add(Tre* root, string find, string input)
{
Tre* p = root;
p = search(root, find);
if (p->left != NULL)
{
p->right = new Tre(p, input);
//p->left = new Tre(p, input);
}
else if (p->left == NULL)
{
p->left = new Tre(p, input);
//p->right = new Tre(p, input);
}
return root;
}
Tre* del(Tre* root, string data)
{
Tre* p = root, * q;
p = search(root, data);
q = p->parent;
if (q->right != NULL && q->right->data == data)
{
q->right = NULL;
delete p;
}
else if (q->left->data == data)
{
q->left = NULL;
delete p;
}
return root;
}
Tre* modify(Tre* root, string find, string input)
{
Tre* p = root;
p = search(p, find);
p->data = input;
return root;
}
public:
void create_tree();
void display_tree();
void add_tree();
void delete_tree();
void modify_tree();
};
#endif
#endif
Implementation file:
#include "Tree.h"
void Tree::create_tree()
{
string data;
cout << "Input data : "; cin >> data;
create(root, data);
}
void Tree::display_tree()
{
dis(root);
}
void Tree::add_tree()
{
string find, input;
cout << "Parent data : "; cin >> find;
cout << "New data : "; cin >> input;
add(root, find, input);
}
void Tree::delete_tree()
{
string data;
cout << "Delete data : "; cin >> data;
del(root, data);
}
void Tree::modify_tree()
{
string find, input;
cout << "Find data : "; cin >> find;
cout << "New data : "; cin >> input;
modify(root, find, input);
}
I am worked on a Linked list stack and a bunch of functions for it. What I do not understand currently is how come my "isEmpty" function is not working correctly. I believe that the way I have it written makes sense. By nature if Front is Null then the list should have to be empty which would mean that "isEmpty" would return false. The problem that I am having is that my program says that the list is always empty whether or not it actually is or not. I am not sure what the issue is. Any help would be appreciated.
struct node
{
int data;
node *next;
}*front = NULL, *rear = NULL, *p = NULL, *np = NULL;
void push(int x)
{
np = new node;
np->data = x;
np->next = NULL;
if(front == NULL)
{
front = rear = np;
rear->next = NULL;
}
else
{
rear->next = np;
rear = np;
rear->next = NULL;
}
}
int pop()
{
int x;
if (front == NULL)
{
cout<<"empty queue\n";
}
else
{
p = front;
x = p->data;
front = front->next;
delete(p);
return(x);
}
}
int peek()
{
int x;
if (front == NULL)
{
cout<<"empty queue\n";
}
else
{
p = front;
x = p->data;
front = front->next;
return(x);
}
}
bool isEmpty()
{
if (front == NULL)
{
return true;
}
else if (front != NULL)
{
return false;
}
}
void Display()
{
cout << front;
}
int main()
{
int n, c = 0, x;
bool is_empty = isEmpty();
cout<<"Enter the number of values to be pushed into queue\n";
cin>>n;
while (c < n)
{
cout<<"Enter the value to be entered into queue\n";
cin>>x;
push(x);
c++;
}
cout<<endl<<"Pop value: ";
if (front != NULL)
cout<<pop()<<endl;
cout<<endl<<"Peak value: ";
if (front != NULL)
cout<<peek()<<endl;
if (is_empty == true)
{
cout<<endl<<"The list is empty";
}
else if (is_empty == false)
{
cout<<endl<<"The list is not empty";
}
cout << endl << "The current contents of the stack are: ";
while(front != NULL)
{
Display();
if(front == NULL)
cout << "The stack is empty";
break;
}
getch();
}
There are some issues with your code.
You have defined an isEmpty() function, but you don't really it. You have declared a separate variable is_empty that you set to the return value of isEmpty() one time before you populate the list, and never update is_empty after making any changes to the list. That is why your code is always reporting the list is "empty" even if it is really not. You need to get rid of the is_empty variable and call isEmpty() every time you need to check for empty.
Also, the return value of peek() and pop() are indeterminate if front is NULL.
And peek() pops the front node from the list. Only pop() should be doing that.
And pop() does not check if rear is pointing at the node being popped. You are not resetting rear to NULL in that case.
And you don't free any nodes remaining in the list before exiting the program.
Try something more like this instead:
#include <iostream>
#include <limits>
struct node
{
int data;
node *next;
node(int value): data(value), next(NULL) {}
};
node *front = NULL;
node *rear = NULL;
void push(int x)
{
node **np = (rear) ? &(rear->next) : &front;
*np = new node(x);
rear = *np;
}
int peek()
{
if (front)
return front->data;
return -1;
}
int pop()
{
int x = peek();
if (front)
{
node *p = front;
front = front->next;
if (p == rear) rear = NULL;
delete p;
}
return x;
}
bool isEmpty()
{
return !front;
}
void clear()
{
while (front)
{
node *p = front;
front = front->next;
delete p;
}
rear = NULL;
}
void display()
{
node *n = front;
if (n)
{
cout << n->data;
while (n = n->next)
cout << ' ' << n->data;
}
}
int askForNumber(const char *prompt)
{
int n;
cout << prompt << ": ";
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return n;
}
int main()
{
int n, x;
n = askForNumber("Enter the number of values to be pushed into queue");
for(int c = 0; c < n; ++c)
{
x = askForNumber("Enter the value to be entered into queue");
push(x);
}
cout << endl;
cout << "Pop value: ";
if (!isEmpty())
cout << pop();
else
cout << "empty queue";
cout << endl;
cout << "Peak value: ";
if (!isEmpty())
cout << peek();
else
cout << "empty queue";
cout << endl;
if (isEmpty())
cout << "The list is empty";
else
cout << "The list is not empty";
cout << endl;
cout << "The current contents of the stack are:" << endl;
display();
cout << endl;
clear();
cin.get();
return 0;
}
I do not know why this code breaks ,probably when adding new node, on Windows .Returns "Process returned -1073741819 (0xC0000005)"),it was compiled with GNU GCC.It works perfectly fine on Linux.
Also tested on geeksforgeeks ide , this is the link https://ide.geeksforgeeks.org/feo8SYMsFP.
When debugged, SIGSEGV is returned when adding node but I am not sure why..
For example, input : 1 10 1 11 then it breaks..
#include <iostream>
#include <stdlib.h>
struct Node
{
int key;
Node * left;
Node * right;
};
class binarySearchTree
{
private:
Node *root;
Node *newNode(int key)
{
Node *temp = new Node;
temp->left = temp->right = NULL;
temp->key = key;
return temp;
}
void traverse_inorder(Node *temp)
{
if (temp==NULL)
return;
traverse_inorder(temp->left);
std::cout <<"Current key: "<< temp->key << "\n";
traverse_inorder(temp->right);
}
void find(Node* temp,int key)
{
if (temp==NULL)
return;
find(temp->left,key);
if (temp->key == key)
std::cout <<"Key " << key << " found\n";
find(temp->right,key);
}
Node* minValueNode(Node* n)
{
Node* x = n;
while (x->left != NULL)
x = x->left;
return x;
}
Node* deleteNode(Node* temp, int key)
{
if (temp == NULL)
return temp;
if (key < temp->key)
temp->left = deleteNode(temp->left, key);
else if (key > temp->key)
temp->right = deleteNode(temp->right, key);
else
{
if (temp->left == NULL)
{
Node *x = temp->right;
delete temp;
return x;
}
else if (root->right == NULL)
{
Node *x = temp->left;
delete temp;
return x;
}
Node* x = minValueNode(temp->right);
temp->key = x->key;
temp->right = deleteNode(temp->right, x->key);
}
return temp;
}
void delete_tree(Node *temp)
{
if (temp == NULL)
return;
delete_tree(temp->left);
delete_tree(temp->right);
delete temp;
}
void traverse_postorder(Node* temp)
{
if (temp == NULL)
return;
traverse_postorder(temp->left);
traverse_postorder(temp->right);
std::cout <<"Current key: "<< temp->key << "\n";
}
void traverse_preorder(Node* temp)
{
if (temp == NULL)
return;
std::cout <<"Current key: "<< temp->key << "\n";
traverse_preorder(temp->left);
traverse_preorder(temp->right);
}
void add(int key)
{
if (root == NULL)
root = newNode(key);
else
{
Node *temp = root;
while (true)
{
if (temp->key > key)
{
if (temp->left == NULL)
{
temp->left = newNode(key);
break;
}
else
temp = temp->left;
}
else if (temp->key < key)
{
if (temp->right == NULL)
{
temp->right =newNode(key);
break;
}
else
temp = temp->right;
}
else
{
std::cout << "Key already added!\n";
break;
}
}
}
}
public:
binarySearchTree()
{
root = NULL;
}
~binarySearchTree()
{
delete_tree(root);
}
void _find(int key)
{
find(root,key);
}
void _del(int key)
{
root = deleteNode(root,key);
}
void _traverse_postorder()
{
traverse_postorder(root);
}
void _traverse_preorder()
{
traverse_preorder(root);
}
void _traverse_inorder()
{
traverse_inorder(root);
}
void _add(int key)
{
add(key);
}
};
int main()
{
binarySearchTree bst;
std::cout << "Binary Search Tree Menu (1-add key, 2-search key, 3-remove key, 4-traverse inorder, 5-traverse postorder, 6-traverse preorder, q-exit)\n";
char input;
do
{
std::cout << "Awaiting input ";
std::cin >> input;
int key;
switch(input)
{
case '1':
std::cout << "Enter key.. ";
std::cin >> key;
bst._add(key);
break;
case '2':
std::cout << "Enter key.. ";
std::cin >> key;
bst._find(key);
break;
case '3':
std::cout << "Enter key.. ";
std::cin>>key;
bst._del(key);
break;
case '4':
bst._traverse_inorder();
break;
case '5':
bst._traverse_postorder();
break;
case '6':
bst._traverse_preorder();
break;
}
}
while (input != 'q');
std::cout << "Deleting Binary Search Tree...\n";
return 0;
}
This code:
struct Node
{
int key;
Node * left;
Node * right;
};
Node *newNode(int key)
{
Node *temp = new Node;
temp->key = key;
return temp;
}
means that newNode returns pointer to node with indeterminate values for left and right. Instead these should be null pointers, (e.g. use new Node(); instead of new Node;).
On the original system it probably happened to get zeroed memory from the allocator so the problem didn't show up.
Adding integers to list works fine, but there's something wrong with deleting and printing.
I'm not friendly with debugger yet, but I found out that there is error from node pointer 'first'. Its value is -17891602. I don't know what happened...
#include <iostream>
using namespace std;
class nodeList;
class node {
friend class nodeList;
private:
int data;
node* link;
public:
node() { //constructor
data = 0;
link = NULL;
}
node(int d) { //constructor
data = d;
link = NULL;
}
node(int d, node* l){ //constructor
data = d;
link = l;
}
};
class nodeList {
private:
node* first;
int num = 0;
node* nt;
public:
nodeList() {
first = new node();
}
node* end(node* t){ //return pointer of last element
t = first;
for (int i = 0; i < num; i++){
t = t->link;
}
return t;
}
void add(int a){ //add 'a' at the end of the list
node* x = new node(a);
node* y = this->end(nt);
y->link = x;
num++;
}
void del(int n){ //n : data of element that you want to delete from list
node* temp = first;
node* pretemp = NULL;
node* x;
int i;
for (i = 0; i <= this->num; i++){ //loop to find 'n'
pretemp = temp;
temp = temp->link;
if (n == temp->data){
break;
}
}
temp = first;
for (int j = 0; j<i; j++){ //i : where 'n' is,
temp = temp->link;
}
x = temp->link;
pretemp->link = x;
delete temp;
num--;
}
void printList(){
node* temp = first;
temp = temp->link;
for (int i = 0; i<this->num; i++){
cout << temp->data << endl;
temp = temp->link;
}
}
};
int main(){
nodeList *l = new nodeList();
int a;
int select;
while (1){
cout << "1. ADD 2. DELETE 3. PRINT" << endl;
cin >> select;
if (select == 1){
cout << "Enter an integer: ";
cin >> a;
if (cin.fail()) {
cout << "Wrong input" << endl;
break;
}
l->add(a);
l->printList();
}
if (select == 2){
cout << "Enter the data of the element you want to delete: ";
cin >> a;
if (cin.fail()) {
cout << "Wrong input" << endl;
break;
}
l->del(a);
l->printList();
}
if (select == 3){
l->printList();
}
}
}
Your del function deletes pretemp node (node that was before the one that you need to delete).
Here's possible fix:
//n : data of element that you want to delete from list
void del(int n)
{
//loop to find 'n'
for (node *tmp = first; tmp->link; tmp = tmp->link)
{
if (n == tmp->link->data)
{
node *x = tmp->link;
tmp->link = tmp->link->link;
delete x;
num--;
break;
}
}
}
Also, was your del supposed to delete all nodes with data == n?
These functions are a bit complicated. Here is a simpler idea:
void del(int n){
node* pretemp = first, *temp = first->link;
if(pretemp->data == n) { //handle the deleting of the first node
first = first->link;
delete pretemp;
return;
}
while(temp != NULL && temp->data != n) { //find the node with the data member "n"
pretemp = temp;
temp = temp->link;
}
if(temp != NULL) { //if you found the node, delete it
pretemp->link = temp->link;
delete temp;
}
--num;
}
Your code is a bit over-complicated for what it needs.
Try something more like this instead:
#include <iostream>
#include <limits>
using namespace std;
class nodeList;
class node
{
friend class nodeList;
private:
int data;
node* link;
public:
node(int d = 0) //constructor
: data(d), link(NULL)
{
}
};
class nodeList
{
private:
node* first;
int num;
public:
nodeList()
: first(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->link;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
else
{
node *t = first;
while (t->link)
t = t->link;
t->link = n;
}
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
node* n = first;
node* prev = NULL;
while (n) //loop to find 'data'
{
if (data == n->data)
{
if (prev)
prev->link = n->link;
if (n == first)
first = n->link;
delete n;
--num;
return;
}
prev = n;
n = n->link;
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->link)
cout << n->data << endl;
}
};
int main()
{
nodeList l;
int input;
bool keepGoing = true;
do
{
cout << "1. ADD 2. DELETE 3. PRINT 4. EXIT" << endl;
if (!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
switch (input)
{
case 1:
cout << "Enter an integer: ";
if (!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
l.add(input);
l.printList();
}
break;
case 2:
cout << "Enter the data of the element you want to delete: ";
if(!(cin >> input))
{
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
}
else
{
l.del(input);
l.printList();
}
break;
case 3:
l.printList();
break;
case 4:
keepGoing = false;
break;
default:
cout << "Wrong input" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
break;
}
}
}
while (keepGoing);
return 0;
}
If you add an extra node* member to your nodeList class, you can simplify and speed up your add() method:
class nodeList
{
private:
node* first;
node* last;
int num;
public:
nodeList()
: first(NULL), last(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->link;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
if (last)
last->link = n;
last = n;
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
node* n = first;
node* prev = NULL;
while (n) //loop to find 'data'
{
if (data == n->data)
{
if (prev)
prev->link = n->link;
if (n == first)
first = n->link;
if (n == last)
last = prev;
delete n;
--num;
return;
}
prev = n;
n = n->link;
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->link)
cout << n->data << endl;
}
};
And if you can change your list to be a double-linked list instead of a single-linked list, you can simplify your del() method as well:
#include <iostream>
#include <limits>
using namespace std;
class nodeList;
class node
{
friend class nodeList;
private:
int data;
node* prev;
node* next;
public:
node(int d = 0) //constructor
: data(d), prev(NULL), next(NULL)
{
}
};
class nodeList
{
private:
node* first;
node* last;
int num;
public:
nodeList()
: first(NULL), last(NULL), num(0)
{
}
~nodeList()
{
node *n = first, *t;
while (n)
{
t = n->next;
delete n;
n = t;
}
}
void add(int data) //add 'data' at the end of the list
{
node* n = new node(data);
if (!first)
first = n;
if (last)
last->next = n;
n->prev = last;
last = n;
++num;
}
void del(int data) //data : data of element that you want to delete from list
{
for(node* n = first; n != NULL; n = n->next) //loop to find 'data'
{
if (data == n->data)
{
if (n->prev)
n->prev->next = n->next;
if (n->next)
n->next->prev = n->prev;
if (n == first)
first = n->next;
if (n == last)
last = n->prev;
delete n;
--num;
return;
}
}
}
void printList()
{
for(node* n = first; n != NULL; n = n->next)
cout << n->data << endl;
}
};
I'm trying to create a program that gets string input from a text file, inserting the content into a list, word by word. I also have to calculate the numbers of the duplicates. My program works fine for the small input text file (1 line of string). But whenever I feed it with a bigger text file, it crashes. Any help will be great.
Here is my code:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
class Bag
{
private:
struct BagNode
{
string dataValue;
int dataCount;
BagNode *next;
BagNode(string);
};
BagNode *root;
string removePunctuations(string);
string toLower(string);
void insertData(string);
public:
Bag();
void procesFile(string, string);
void removeData(string);
void traverse();
};
Bag::BagNode::BagNode(string _data)
{
dataValue.assign(_data);
dataCount=1;
next = NULL;
}
Bag::Bag()
{
root = NULL;
}
void Bag::procesFile(string ifile, string ofile)
{
ifstream infile;
infile.open(ifile.c_str());
if (!infile.good())
{
cout<<"Input file not opening."<<endl;
return;
}
string line;
while(getline(infile,line))
{
stringstream lineStream(line);
string token = "";
while(lineStream >> token)
{
insertData(removePunctuations(token));
}
}
infile.close();
traverse();
cout<< endl <<"File processed successfully." << endl;
}
string Bag::removePunctuations(string data)
{
int length = data.size();
for(int i = 0; i < length; i++)
{
if(ispunct(data[i]))
{
data.erase(i--, 1);
length = data.size();
}
}
return data;
}
string Bag::toLower(string data)
{
for(int i = 0; data[i]; i++){
data[i] = tolower(data[i]);
}
return data;
}
void Bag::insertData(string data)
{
BagNode *n = new BagNode(data);
if (root == NULL)
{
root = n;
return;
}
BagNode *temp = root;
BagNode *prev = NULL;
string tdata;
data.assign(toLower(data));
while(temp != NULL)
{
tdata.assign(temp->dataValue);
tdata.assign(toLower(tdata));
if (tdata.compare(data) == 0)
{
temp->dataCount++;
return;
}
else
{
if (data.compare(tdata) < 0)
{
if (temp == root)
{
n->next = temp;
root = n;
return;
}
else
{
n->next = temp;
prev->next = n;
return;
}
}
}
prev = temp;
temp = temp->next;
}
n->next = temp;
prev->next = n;
}
void Bag::removeData(string data)
{
BagNode *temp = root;
BagNode *prev = NULL;
if (root->dataValue.compare(data)==0)
{
if (root->dataCount > 1)
root->dataCount--;
else
{
delete root;
root = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
while (temp != NULL)
{
if (temp->dataValue.compare(data)==0)
{
if (temp->dataCount > 1)
temp->dataCount--;
else
{
prev->next = temp->next;
delete temp;
temp = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
prev = temp;
temp = temp->next;
}
cout<<"Data not found match."<<endl;
}
void Bag::traverse()
{
if (root == NULL)
{
cout<<"No data."<<endl;
return;
}
BagNode *temp = root;
while(temp != NULL)
{
if (temp->dataCount > 1)
cout << temp -> dataValue << "(" << temp->dataCount << ")" << endl;
else
cout << temp -> dataValue << endl;
temp = temp->next;
}
}
int main(int argc, char *argv[])
{
bool outputConsole = false;
string infile, outfile = "\0";
cout << "Welcome!" << endl;
int option = -1;
do{
if (argc==1 || option == 1)
{
cout << "Enter the input file: ";
cin >> infile;
cout << "Enter the output file: ";
cin >> outfile;
}
else
{
infile.assign(argv[1]);
if (argc == 3)
outfile.assign(argv[2]);
}
Bag b;
b.procesFile(infile,outfile);
//b.traverse();
cout<<endl<<"If you want to input another file press 1 or 2 to quit: ";
cin>>option;
}while (option != 2);
return 0;
}
If ordering of words is not an issue,you should really try and use a hash table instead of a linked list as hash table is suitable for keeping track of duplicates.This will lead to O(1) insert operation (in ideal situation)