C++ tree data structure Access violation with String - c++

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);
}

Related

Difficulty printing data in my binary tree in print method

I'm trying to add data to a binary tree, however when I run a method that prints the data of the binarytree in order, nothing prints, and the program exits when it should be printing. I've tested it to see if data is actually being added by having the name and weight values of the rootNode print themselves inside the add method everytime its called, but I cannot get the same results inside of the inOrder method. I believe my issue has something to do with the node being passed.
#include <iostream>
using namespace std;
struct node {
int weight;
string name;
node *left, *right;
};
struct node* newNode(int dataw, string datan)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->weight = dataw;
node->name = datan;
node->left = NULL;
node->right = NULL;
return (node);
}
void add(node *rootNode, int dataw, string datan)
{
int lowest_weight;
if (rootNode == NULL )
{
rootNode = newNode(dataw,datan);
lowest_weight = dataw;
}
else
{
if (datan < rootNode->name)
{
if (rootNode->left == NULL)
{
rootNode->left = newNode(dataw,datan);
}
else
{
add(rootNode->left,dataw,datan);
}
}
else
{
if (rootNode->right == NULL)
{
rootNode->right = newNode(dataw,datan);
}
else
{
add(rootNode->right, dataw, datan);
}
}
}
}
void inOrder(node *next)
{
if (next!=NULL)
{
inOrder(next->left);
cout << next->name << " " << next->weight << endl;
inOrder(next->right);
}
}
int main()
{
node *rootNode = NULL;
int height {}, leaves {}, weight {};
string name;
do
{
cout << "Enter name: ";
cin >> name;
if (name == "-1")
break;
cout << "Enter weight: ";
cin >> weight;
add(rootNode, weight, name);
} while (name!="-1");
inOrder(rootNode);
return 0;
}
Resolved it, had to assign the rootNode declaration to a new node method call so the data is not always NULL
node *rootNode = newNode(weight,name);

C++ code working as intended on Linux but not on Windows

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.

A ton of undefined reference errors

I don't know if I'm linking wrong but I'm compiling this on linux and I'm getting a LOT of undefined references for my node functions. I'm writing a binary search tree to searches for telephones for class that is due tonight.
bst.cpp
#include "bst.hpp"
BST::BST(void)
{
count = 0;
root = NULL;
}
void BST::insert(long long x, string y)
{
Node *newnode = new Node(x, y);
Node *temp;
if (count == 0)
{
root = newnode;
count++;
}
else
{
while(temp->getleft() != NULL && temp->getright() != NULL)
{
if(newnode->getnum() < temp->getnum())
{
temp = temp->getleft();
}
else
{
temp = temp->getright();
}
}
if (newnode->getnum() < temp->getnum())
{
temp->setleft(newnode);
}
else
{
temp->setright(newnode);
}
}
}
Node * BST::getroot(void)
{
return root;
}
Node* BST::delete_node(Node *troot, long long key)
{
if (count == 0)
{
return troot;
}
else if(key < troot->getnum())
{
delete_node(troot->getleft(), key);
}
else if (key > troot->getnum())
{
delete_node(troot->getright(), key);
}
else
{
if(troot->getleft() == NULL && troot->getright() == NULL)
{
delete troot;
troot == NULL;
}
else if(troot->getright() == NULL)
{
Node *temp = troot;
troot = troot->getleft();
delete temp;
}
else if(troot->getleft() == NULL)
{
Node *temp = troot;
troot = troot->getright();
delete temp;
}
}
return troot;
}
void BST::preverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
preverse(troot->getleft());
preverse(troot->getright());
}
void BST::postverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
postverse(troot->getleft());
postverse(troot->getright());
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
}
void BST::inverse(Node* troot)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
inverse(troot->getleft());
cout << troot->getname() << endl;
cout << troot->getnum() << endl;
inverse(troot->getright());
}
void BST::search(Node* troot, long long key)
{
if(root == NULL)
{
cout << "The tree is empty\n";
}
if(troot == NULL)
{
return;
}
if(key == troot->getnum())
{
cout << troot->getname();
}
search(troot->getleft(), key);
search(troot->getright(), key);
}
bst.hpp
#include "node.hpp"
#ifndef bst_hpp
#define bst_hpp
class BST
{
Node* root;
long long count;
public:
BST(void);
void insert(long long x, string y);
Node* getroot(void);
Node* delete_node(Node* troot, long long key);
void preverse(Node* troot);
void postverse(Node* troot);
void inverse(Node* troot);
void search(Node* troot, long long key);
};
#endif
node.cpp
#include "node.hpp"
Node::Node(void)
{
number = 0;
name = "no name";
left = NULL;
right = NULL;
}
Node::Node(long long t, string n)
{
number = t;
name = n;
left = NULL;
right = NULL;
}
Node * Node::getleft(void)
{
return left;
}
Node * Node::getright(void)
{
return right;
}
void Node::setleft(Node * ptr)
{
left = ptr;
}
void Node::setright(Node * ptr)
{
right = ptr;
}
long long Node::getnum(void)
{
return number;
}
string Node::getname(void)
{
return name;
}
node.hpp
#ifndef node_hpp
#define node_hpp
#include <string>
#include <iostream>
using namespace std;
class Node
{
long long number;
string name;
Node *left;
Node *right;
public:
Node(void);
Node(long long t, string n);
Node* getleft(void);
Node* getright(void);
void setleft(Node* ptr);
void setright(Node* ptr);
long long getnum(void);
string getname(void);
};
#endif
main.cpp
#include "bst.hpp"
using namespace std;
int main(void)
{
int choice;
long long numin;
string input;
BST phbook;
do
{
cout << "1. Insert a name and number.\n2. Delete using number.\n3. Traverse pre-order\n4. Traverse post-order\n";
cout << "5. Traverse in-order\n6. Search using number.\n6. Exit program\n";
switch(choice)
{
case 1:
cout << "Enter a name\n";
cin.ignore();
getline(cin, input);
cout << "Enter a number\n";
cin >> numin;
phbook.insert(numin, input);
break;
case 2:
cout << "Enter the phone number you'd like to delete.\n";
cin >> numin;
phbook.delete_node(phbook.getroot(), numin);
break;
case 3:
phbook.preverse(phbook.getroot());
break;
case 4:
phbook.postverse(phbook.getroot());
break;
case 5:
phbook.inverse(phbook.getroot());
break;
case 6:
cout << "Enter a phone number to search.\n";
cin >> numin;
phbook.search(phbook.getroot(),numin);
default:
numin=numin;
}
}while(choice >= 1 && choice <= 6);
return 0;
}
To me, nothing looks wrong in linking the files.
Some examples : undefined reference to Node::getnum()
undefined reference to Node::getname()
Check the order of compiled elements:
g++ node.cpp -o node.o bst.cpp -o bst.o main.cpp -o main.o
Result:
./main.o
1. Insert a name and number.
2. Delete using number.
3. Traverse pre-order
4. Traverse post-order
5. Traverse in-order
6. Search using number.
6. Exit program

Output of c++ program not coming as expected

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;
}

C++ Linked List node counting (need help)

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)