Runtime error when using struct as value in std::map? - c++

I am using a map with int value -> trie, trie is the struct. So why am I getting runtime error when I print all keys value in my map? But if I don't print anything then there is no error(the insert() part don't cause any error).
struct trie{
node *root;
trie(){
root = new node();
}
void insert(int x){
node *cur = root;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b] == NULL) cur->child[b] = new node();
cur = cur->child[b];
}
cur->isleaf = true;
}
int maxxor(int x){
node *cur = root;
int res = 0;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b ^ 1] != NULL){
res |= (1ll << i);
cur = cur->child[b ^ 1];
}
else cur = cur->child[b];
}
return res;
}
int minxor(int x){
node *cur = root;
int res = 0;
for(int i = 31; i >= 0; i--){
int b = (x >> i) & 1;
if (cur->child[b] != NULL) cur = cur->child[b];
else{
res |= (1ll << i);
cur = cur->child[b ^ 1];
}
}
return res;
}
~trie(){
delete root;
}
};
map<int, trie> tr;
int32_t main(){
ios::sync_with_stdio(false);
tr[3].insert(1);// no error
for(auto x: tr) cout << x.first << ' '; //RUNTIME ERROR?
}
I have tried to debug and read various questions/answers but I still not be able to debug this code. Any help are appreciated.

You have implemented a "complex" tree if i may say, using linked list. And in order to avoid trouble, you need to make sure that your destructors do their work propoerly and are coherent i.e destroy all allocated memory and don't "try" to "destroy" unallocated space or already destroyed space.
That said, your trie destructor destroys root data member, which calls node destructor. And node destructor destroys both two child which were not necessarily allocated. This is the origin of your Segmentation Error.
To correct this you should only destroy allocated child.
Here is a simplified version of your code
#include <bits/stdc++.h>
#define int int64_t
using namespace std;
struct node{
node* child[2];
bool isleaf;
node(){
child[0] = child[1] = NULL;
isleaf = false;
}
~node(){
}
};
struct trie{
node *root;
trie(){
cout << " in trie ctor" << endl;
root = new node();
}
void insert(int x){
cout << "in insert trie methode " << endl;
node *cur = root;
cur->child[0] = new node();
cur->child[1] = new node();
}
~trie(){
delete root->child[0]; // i'm sure it has been allocated
delete root->child[1]; // i'm sure it has been allocated
// delete root, would be like doing int *p; delete p;
}
};
map<int, trie> tr;
int32_t main(){
ios::sync_with_stdio(false);
tr[3].insert(1);
for(auto x: tr)
cout << x.first << endl << endl;
}

Related

dynamically allocated struct array for open hash table

I am trying to implement a simple open hash in c++ for the sake of learning. I am getting very confused about the interaction of functions with array pointers, and I am at the end of my wits.
The code:
struct node{
int data;
node* next;
node* prev;
bool state;
node(){
prev = next = NULL;
state = true;
}
};
//state true means empty, state false means full.
void insert(node *array,int value){
node *current = array;
if(array->state == true){
array->data = value;
array->state = false;
} else {
node* add = new node();
add->data = value;
add->state = false;
while(current->next != NULL){
current = current->next;
}
current->next = add;
add->prev = current;
}
}
void display(node *array, int size){
node *show = new node();
for(int i = 0; i< size; i++){
if(array->state == false){
cout<<array->data;
show = array;
while(show->next != NULL){
show = show->next;
cout<<" --> "<<show->data;
}
} else {
cout<<"Empty.";
}
cout<<"\n\n";
}
}
int main(){
int size;
cout<<"Enter size of the hash table: ";
cin>>size;
node *array = new node[size];
int value;
cout<<"Enter Value: ";
cin>>value;
int index = value%size;
//inserting single value
insert(&array[index],value);
//Hash table output.
display(array,size);
return 0;
}
When I run this code, instead of showing "empty" in places where the array's state is empty, it seems as if the entire array has the same value. The problem lies in the insert function, but I cannot figure it out.
You can simplify this by making the Hashtable an array of pointers to Node. A nullptr then means the slot is empty and you don't have empty and full nodes. Also Nodes only need a next pointer and usually new entries are added to the beginning of the buckets instead of the end (allows duplicate entries to "replace" older ones). Inserting at the beginning of a list becomes real easy with Node **.
#include <cstddef>
#include <iostream>
struct Table {
struct Node {
Node * next;
int data;
Node(Node **prev, int data_) : next{*prev}, data{data_} {
*prev = this;
}
};
std::size_t size;
Node **tbl;
Table(std::size_t size_) : size{size_}, tbl{new Node*[size]} { }
~Table() {
for (std::size_t i = 0; i < size; ++i) {
Node *p = tbl[i];
while(p) {
Node *t = p->next;
delete p;
p = t;
}
}
delete[] tbl;
}
void insert(int value) {
Node **slot = &tbl[value % size];
new Node(slot, value);
}
void display() const {
for(std::size_t i = 0; i < size; i++) {
std::cout << "Slot " << i << ":";
for (const Node *node = tbl[i]; node; node = node->next) {
std::cout << " " << node->data;
}
std::cout << std::endl;
}
}
};
int main(){
std::size_t size;
std::cout << "Enter size of the hash table: ";
std::cin >> size;
Table table{size};
int value;
std::cout << "Enter Value: ";
std::cin >> value;
//inserting single value
table.insert(value);
//Hash table output.
table.display();
return 0;
}

Unable to overload '[ ]' in here. C++ Noob here

I am trying to implement a linkedlist in C++ and trying to incorporate array like data access using '[]'.
First I declared a Node class as the following.
class Node{
public:
int data;
Node *next, *prev;
Node(int val){
this -> data = val;
this -> next = NULL;
this -> prev = NULL;
}
};
Then I implemented the Linkedlist class as the following where I have overloaded the '[]' operator like the following
class LinkedList{
public:
Node *head;
LinkedList(){
this -> head = NULL;
}
LinkedList(Node *h){
this -> head = h;
}
int operator [] (int index){
if(index < 0 || index >= getsize(this -> head)){
cout << "List out of bounds" << endl;
return -1;
}else{
Node *cur = this -> getnode(index);
return cur -> data;
}
}
Node* getnode(int index){
int count = 0;
Node *cur = this -> head;
while(cur != NULL){
if(count == index)
break;
count++;
cur = cur -> next;
}
return cur;
}
};
In the main function I have tried to print the 'l[0]'. It shows error as
no operator "<<" matches these operandsC/C++(349)
linklist_sort.cpp(173, 10): operand types are: std::ostream << LinkedList
Please help me out. Am I missing some concept here ?
The main function :
int main(){
srand(time(0));
LinkedList *l = new LinkedList();
for(int i = 0; i<10; i++){
int num = rand() % 50 + 1;
l -> head = l -> insert(l->head,num);
}
l->printlist(l->head);
int n1, n2;
cout << "\n";
cin >> n1 >> n2;
l->swap(l->head,n1,n2);
l->printlist(l->head);
cout << "\n";
cout << l[0]; //Error here
return 0;
}
The getsize function :
int getsize(Node *head){
if(head == NULL)
return 0;
else
return 1 + getsize(head->next);
}
Since l is a pointer which is created by
LinkedList *l = new LinkedList();
it needs to be dereferenced to be able to use operator first.
This would solve your problem:
cout << (*l)[0];
But I suggest you to not create LinkedList with new keyword so you can avoid using raw pointers and memory leaks in the application code.
You could use LinkedList l; instead.

How to create and execute a copy constructor for a linked list?

I have tried looking at videos and older posts but it is still very difficult to understand the concept of copy constructors. Would someone clear it up for me? My class did not really cover this part 100% my professor focused mainly on constructors and destructors.
Main CPP
#include <iostream>
#include "Header.h"
using namespace std;
int main()
{
node access;
access.getData();
access.outData();
system("pause");
return 0;
}
Header File
#include <iostream>
using namespace std;
class node
{
public:
node(); // Had to create my own default constructor because of my copy constructor.
node(const node &n); // This is a copy constructor.
~node();
void getData();
void outData();
private:
int num;
int lCount = 0; // Counts the number of nodes, increments after each user input.
int *ptr; // Where the linked list will be copied into
node *next;
node *first;
node *temp;
node *point;
};
node::node()
{
num = 0;
}
node::node(const node &n)
{
temp = first;
ptr = new node;
for (int i = 0; i < lCount; i++)
{
ptr[i] = temp->num;
temp = temp->next;
}
}
node::~node() // Deletes the linked list.
{
while (first != NULL)
{
node *delP = first; // Creates a pointer delP pointing to the first node.
first = first->next; // "Removes first node from the list and declares new first.
delete delP; // Deletes the node that was just removed.
}
cout << "List deleted" << endl;
}
void node::getData() // Simple function that creates a linked list with user input.
{
int input = 0;
point = new node;
first = point;
temp = point;
while (input != -1)
{
cout << "Enter any integer, -1 to end." << endl;
cin >> input;
if (input == -1)
{
point->next = NULL;
break;
}
else
{
lCount++;
point->num = input;
temp = new node;
point->next = temp;
point = temp;
}
}
}
void node::outData()
{
temp = first;
cout << "Original" << endl;
while (temp->next != NULL)
{
cout << temp->num << endl;
temp = temp->next;
}
cout << "Copied" << endl;
for (int i = 0; i < lCount; i++)
{
cout << ptr[i] << endl;
}
}
This little snippet is what I am having trouble with in particular:
node::node(const node &n)
{
temp = first;
ptr = new node;
for (int i = 0; i < lCount; i++)
{
ptr[i] = temp->num;
temp = temp->next;
}
}
I figured it out! I was tinkering with a much simpler copy constructor. I was having trouble understanding syntax, everything was very complicated and it was overwhelming to look at.
#include <iostream>
using namespace std;
class node
{
public:
node(int x); // Normal Construtor
node(const node &cpy); // Copy Constructor
void change(); // Changes data value
void outData();
private:
int data;
};
int main()
{
node var1(123);
var1.outData();
node var2 = var1;
var2.outData();
var2.change();
var1.outData();
var2.outData();
system("pause");
return 0;
}
node::node(int x)
{
data = x;
}
node::node(const node &cpy)
{
data = cpy.data;
}
void node::outData()
{
cout << data << endl;
}
void node::change()
{
int userIn;
cin >> userIn;
data = userIn;
}
Output:
123
123
(input: 4444)
Output:
123
4444

c++ Stuck making an binary tree implementation with an array and lists

I am working on writing a list of children binary tree implementation. In my code I have an array of lists. Each list contains a node followed by its children on the tree. I finished writing the code and everything compiled, but I keep getting a segmentation fault error and I cannot figure out why. I have been attempting to debug and figure out where my code messes up. I know that there is an issue with the FIRST function. It causes a segmentation fault. Also, when I try to print just one of the lists of the array, it prints everything. I have been stuck on this for a very long time now and would like some help. Can anyone offer suggestions as to why the FIRST and PRINT functions are not working? Maybe there is a large error that I just cannot see.
My code is as follows:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <array>
#include <string.h>
using namespace std;
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
void ADD(char n);
node* CREATE(char n);
void BEGIN(char n);
char FIRST();
char END();
char NEXT(char n);
char PREVIOUS(char n);
int LOCATE(char n);
void EMPTY();
void PRINT();
list()
{
start = NULL;
}
};
char PARENT(const char n, list tree[], int length)
{
int i=0;
list l;
for (i; i<length; i++)
{
l = tree[i];
if (n != l.FIRST())
{
if (l.LOCATE(n)>0)
return l.FIRST();
}
}
}
char LEFTMOST_CHILD(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if (l.FIRST() == n)
return l.NEXT(n);
}
}
char RIGHT_SIBLING(char n, list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
if(n != l.FIRST())
{
if (l.LOCATE(n) > 0)
{
return l.NEXT(n);
}
}
}
}
char ROOT(list tree[]) //assumes array is in order, root is first item
{
list l;
l = tree[0];
cout << "Assigned tree to l" << endl;
return l.FIRST();
}
void MAKENULL(list tree[], int length)
{
int i;
list l;
for (i=0; i<length; i++)
{
l = tree[i];
l.EMPTY();
}
}
void list::PRINT()
{
struct node *temp;
if (start == NULL)
{
cout << "The list is empty" << endl;
return;
}
temp = start;
cout << "The list is: " << endl;
while (temp != NULL)
{
cout << temp->element << "->" ;
temp = temp->next;
}
cout << "NULL" << endl << endl;
}
void list::EMPTY()
{
struct node *s, *n;
s = start;
while (s != NULL)
{
n = s->next;
free(s);
s = n;
}
start = NULL;
}
int list::LOCATE(char n)
{
int pos = 0;
bool flag = false;
struct node *s;
s = start;
while (s != NULL)
{
pos++;
if (s->element == n)
{
flag == true;
return pos;
}
s = s->next;
}
if (!flag)
return -1;
}
void list::ADD(char n)
{
struct node *temp, *s;
temp = CREATE(n);
s = start;
while (s->next != NULL)
s = s->next;
temp->next = NULL;
s->next = temp;
}
node *list::CREATE(char n)
{
struct node *temp;
temp = new(struct node);
temp->element = n;
temp->next = NULL;
return temp;
}
void list::BEGIN(char n)
{
struct node *temp, *p;
temp = CREATE(n);
if (start == NULL)
{
start = temp;
start->next = NULL;
}
}
char list::FIRST()
{
char n;
struct node *s;
s = start;
cout << "s = start" << endl;
n = s->element;
cout << "n" << endl;
return n;
}
char list::END()
{
struct node *s;
s = start;
int n;
while (s != NULL)
{
n = s->element;
s = s->next;
}
return n;
}
char list::NEXT(char n)
{
char next;
struct node *s;
s = start;
while (s != NULL)
{
if (s->element == n)
break;
s = s->next;
}
s = s->next;
next = s->element;
return next;
}
char list::PREVIOUS(char n)
{
char previous;
struct node *s;
s = start;
while (s != NULL)
{
previous = s->element;
s = s->next;
if (s->element == n)
break;
}
return previous;
}
main()
{
list a,b,c,d,e,f,g,h,i,j,k,l,m,n;
a.BEGIN('A');
b.BEGIN('B');
c.BEGIN('C');
d.BEGIN('D');
e.BEGIN('E');
f.BEGIN('F');
g.BEGIN('G');
h.BEGIN('H');
i.BEGIN('I');
j.BEGIN('J');
k.BEGIN('K');
l.BEGIN('L');
m.BEGIN('M');
n.BEGIN('N');
a.ADD('B');
a.ADD('C');
b.ADD('D');
b.ADD('E');
e.ADD('I');
i.ADD('M');
i.ADD('N');
c.ADD('F');
c.ADD('G');
c.ADD('H');
g.ADD('J');
g.ADD('K');
h.ADD('L');
a.PRINT();
list tree[] = {a,b,c,d,e,f,g,h,i,j,k,l,m,n};
int length = sizeof(tree)/sizeof(char);
char root = ROOT(tree);
cout << "Found root" << endl;
char parent = PARENT('G', tree, length);
cout << "Found Parent" << endl;
char leftChild = LEFTMOST_CHILD('C', tree, length);
cout << "found left child" << endl;
char rightSibling = RIGHT_SIBLING('D', tree, length);
cout << "found right sibling" << endl;
cout << "The root of the tree is: ";
cout << root << endl;
cout << "The parent of G is: ";
cout << parent << endl;
cout << "The leftmost child of C is" ;
cout << leftChild << endl;
cout << "The right sibling of D is: " ;
cout << rightSibling << endl;
}
Any help will be very appreciated. Thanks you!
The fundamental problem is that you have written a lot of code before testing any of it. When you write code, start with something small and simple that works perfectly, add complexity a little at a time, test at every step, and never add to code that doesn't work.
The specific problem (or at least one fatal problem) is here:
struct node
{
char element;
struct node *next;
}*start;
class list
{
public:
//...
list()
{
start = NULL;
}
};
The variable start is a global variable. The class list has no member variables, but uses the global variable. It sets start to NULL every time a list is constructed, and every list messes with the same pointer. The function FIRST dereferences a pointer without checking whether the pointer is NULL, and when it is, you get Undefined Behavior.
It's not entirely clear what you intended, but you seem to misunderstand how variables work in C++.

Segmentation fault when accessing BST child nodes. Why?

Segmentation faults occurring in function tdeleteLeft(x) when i try to access (x->left) in definition below:
void BST::tdeleteLeft(Node* x){
if (x->left == NULL){
tdelete(x);
}
else{
Node* y;
y = max(x->left);
tdelete(x->left);
x = y;}
}
And here is the full program:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;
class BST {
public:
typedef struct node {
int value;
struct node *left;
struct node *right;
node() {
left = NULL;
right = NULL;
}
}Node;
Node *root;
Node* i;
Node* y;
int z;
static int c;
int count();
void inc();
BST(int n);
void tdelete(Node* x);
Node* max(Node* x);
void remove_node(Node* x);
Node* min(Node* x);
void tdeleteLeft(Node* x);
void insert(Node* tree, int val);
};
int main ()
{
// create BST tree with n nodes
BST *tree = new BST(10);
clock_t t;
t = clock();
tree->remove_node(tree->root);
t = clock() - t;
cout << t << " clicks " << ((float)t)/CLOCKS_PER_SEC << "seconds).\n" << endl;
return 0;
}
BST::BST(int n){
c = 1;
z = 0;
Node *root = NULL;
for (int i=0; i<n; i++){
int rando = rand() % 10;
insert(root, rando);
}
cout << "created " << n << "-node BST" << endl;
}
int BST::c;
int BST::count(){
return c;
}
void BST::inc(){
c++;
}
BST::Node* BST::max(Node* x){
if (x->right == NULL){
return x;
}
else
return max(x->right);
}
BST::Node* BST::min(Node* x){
Node* i = x;
while (i->left !=NULL){
i = i->left;
}
return i ;
}
void BST::tdelete(Node* x){
if (x->right!=NULL){
tdelete(x->right);
}
if (x->left!=NULL){
tdelete(x->left);
}
delete(x);
}
void BST::tdeleteLeft(Node* x){
if (x->left == NULL){
tdelete(x);
}
else{
Node* y;
y = max(x->left);
tdelete(x->left);
x = y;}
}
void BST::remove_node(Node* x){
tdeleteLeft(x);
}
void BST::insert(Node *tree, int val){
if(tree==NULL){
BST::Node* tree = new BST::Node();
tree->left = NULL;
tree->right = NULL;
tree->value = val;
c++;
}
else{
if(c%2==0){
insert(tree->left, val);}
else
insert(tree->right, val);}
}
For one thing, the following declaration of the local variable root in BST::BST(int)
BST::BST(int n){
c = 1;
z = 0;
Node *root = NULL; // <--- This defines a local variable which shadows BST::root
for (int i=0; i<n; i++){
...
shadows the member of the same name. Correspondingly, tree->root in main remains uninitialized after the call to the constructor.
As a result tree->remove_node(tree->root) attempt to delete the "left" node of an uninitialized pointer, which result in the segmentation fault you are observing. To resolve that problem, you need to remove the local declaration of the root variable:
BST::BST(int n){
c = 1;
z = 0;
for (int i=0; i<n; i++){
...
Then you should note that insert(root, rando) does not update the root variable in the caller context since the pointer is passed by value, so the allocated tree nodes become unreachable. To prevent this, you could either return the updated root node with:
Node* BST::insert(Node* tree, int val){
if(tree==NULL){
tree = new BST::Node(); // careful about shadowing the "tree" argument
...
}
else{
if(c%2==0){
tree->left = insert(tree->left, val);
}
else{
tree->right = insert(tree->right, val);
}
}
return tree;
}
which you'd call in the constructor like so:
BST::BST(int n){
c = 1;
z = 0;
for (int i=0; i<n; i++){
int rando = rand() % 10;
root = insert(root, rando);
}
}
or pass the pointer by reference:
void BST::insert(Node*& tree, int val){
...
}