SIGSEGV error occurs in implementation of a hash table in C++ - c++

I am trying to implement a hash table data structure in C++, but every time i run the program i get a run time error(SIGSEGV, segmentation fault) in line number 86 like here.
i.e.: putInHash(str,hashTable,m); in main().
This is my code:
#include <iostream>
#include<string.h>
#include<math.h>
#include<stdlib.h>
using namespace std;
typedef struct node
{
struct node *next,*prev;
string data;
}node;
int hashCode(string str)
{
char arr[str.size()+1];
strcpy(arr,str.c_str());
int code=0;
for(int i=0;i<str.size();i++)
{
code+=((i+1)*((int)arr[i]));
}
return code;
}
int compress(int k,int m)
{
double a=(sqrt(5.0)-1)/2;
return floor(m*(fmod(k*a,1)));
}
void display(node* hashTable[],int m)
{
for(int i=0;i<m;i++)
{
cout<<i<<":\n";
node* p=hashTable[i];
while(p!=NULL)
{
cout<<p->data<<" , ";
}
cout<<"\n";
}
}
void putInHash(string str,node* hashTable[],int m)
{
int k=hashCode(str);
int bucket=compress(k,m);
if(hashTable[bucket]==NULL)
{
hashTable[bucket]=(node*)malloc(sizeof(node));
hashTable[bucket]->prev=NULL;
hashTable[bucket]->next=NULL;
hashTable[bucket]->data=str;
}
else
{
node* temp=(node*)malloc(sizeof(node));
temp->data=str;
temp->next=hashTable[bucket];
hashTable[bucket]->prev=temp;
temp->prev=NULL;
hashTable[bucket]=temp;
}
}
int main()
{
cout<<"Enter number of strings to add in hash table: ";
long int n;
cin>>n;
cout<<"\n";
int m=13;
node* hashTable[m];
for(int i=0;i<m;i++)
{
hashTable[i]=NULL;
}
string str;
cout<<"Enter the strings:\n";
for(int i=0;i<n;i++)
{
cin>>str;
putInHash(str,hashTable,m);
}
display(hashTable,m);
return 0;
}
I thought it might be due to passing the string, but it turned out this wasn't the case.
Can somebody please guide me through it.
I think the error may be in passing the hashTable[] as an argument.

I can't reproduce your problem (I'm using clang++ in a Linux platform and I suppose that your problem is platform dependent) but I see something that can explain it.
You use malloc() to allocate memory for a struct with a std::string in it.
This is bad.
Really, really bad.
Because malloc() can allocate the memory but can't construct the data member in it.
In C++ you should use new; at least, allocating not trivial objects (std::string isn't trivial).
// node* temp=(node*)malloc(sizeof(node)); // DANGEROUS
node * temp = new node;
This is the problem that cause the sigsegv (I suppose) but your code has a lot of other problem.
Example: the while in display() goes in loop because p remain unchanged; you should change display() in this way
void display (node * hashTable[], int m)
{
node * p;
for(int i=0;i<m;i++)
{
cout << i << ":\n";
for ( p = hashTable[i] ; p ; p = p->next )
cout << p->data << " , ";
cout << "\n";
}
}
Another important point: variable length arrays isn't C++; it's C (C99). So this lines are wrong
char arr[str.size()+1];
node* hashTable[m];
You don't need the first (absolutely useless) and you can simplify hashcode() in this way (and please, pass the strings by const reference, when possible)
int hashCode (const string & str)
{
int code = 0;
for ( int i = 0 ; i < str.size() ; ++i )
code += (i+1) * int(str[i]);
return code;
}
About hashTable, you can substitute it with a std::vector
// node* hashTable[m]; no C++
//for(int i=0;i<m;i++) // useless
//{ // useless
// hashTable[i]=NULL; // useless
//} // useless
std::vector<node *> hashTable(m, NULL); // m NULL node pointers
Obviously, putInHash() should be
void putInHash (string str, std::vector<node*> & hashTable, int m)
and display()
void display (const std::vector<node*> & hashTable, int m)
And remember to free the allocated memory.
p.s.: sorry for my bad English.
--- EDIT ---
phonetagger is right: deleting the memory (a vector o linked nodes) isn't trivial.
I suggest a function like the following
void recursiveFreeNode (node * & nd)
{
if ( nd )
{
recursiveFreeNode(nd->next);
delete nd; // added with EDIT 2; sorry
nd = NULL; // useless, in this, case, but good practice
}
}
and call it (for every node of the vector) in main(), after display() calling
for ( unsigned ui = 0U ; ui < hashTable.size() ; ++ui )
recursiveFreeNode(hashTable[ui]);
--- EDIT 2 ---
Sorry: I've forgot the more important line: delete node (thanks phonetagger).
Following the other suggestion of phonetagger, I propose a not-recursive function for deleting the hashtable's node
void loopFreeNode (node * & nd)
{
node * tmp;
for ( ; nd ; nd = tmp )
{
tmp = nd->next;
delete nd;
}
nd = NULL;
}
Obviously the for loop, to use loopFreeNode(), should be
for ( unsigned ui = 0U ; ui < hashTable.size() ; ++ui )
loopFreeNode(hashTable[ui]);

Related

Can't modify a string in C++ array

Trying to learn datastructures, I made this class for a stack. It works just fine with integers but it throws a mysterious error with strings.
The class List is the API for my stack. Its meant to resize automatically when it reaches the limit. The whole code is just for the sake of learning but the error I get doesn't make any sense and it happens somewhere in some assembly code.
#include <iostream>
#include<string>
using namespace std;
class List {
private:
int N = 0;
string* list = new string[1];
void resize(int sz) {
max = sz;
string* oldlist = list;
string* list = new string[max];
for (int i = 0; i < N; i++) {
list[i] = oldlist[i];
}
}
int max = 1;
public:
void push(string str) {
if (N == max) {
resize(2 * N);
}
cout << max << endl;
list[N] = str;
N++;
}
void pop() {
cout << list[--N] << endl;
}
};
int main()
{
string in;
List list;
while (true) {
cin >> in;
if (in == "-") {
list.pop();
}
else {
list.push(in);
}
}
}
string* list = new string[max]; in the resize method defines a new variable named list that "shadows", replaces, the member variable list. The member list goes unchanged and the local variable list goes out of scope at the end of the function, losing all of the work.
To fix: Change
string* list = new string[max];
to
list = new string[max];
so that the function will use the member variable.
Don't forget to delete[] oldlist; when you're done with it to free up the storage it points at.

Null Pointer Error after generating huffman code using recursive call to a function but it is not keeping the NULL value

I was trying to generate huffman code for the input:
testcases=1
string s=abcdef
frequency={5 , 9 ,12 ,13 , 16, 45}
I was trying to traverse through pointers.
I am not sure if there is some error in copying the struct containing pointers because on printing the string it works fine for the nodes containing {12 and 13}
But it does not go back to the next node once it gets to node 5
// { Driver Code Starts
#include<bits/stdc++.h>
using namespace std;
// } Driver Code Ends
struct Node{
int index,frequency;
Node *left,*right;
};
struct comp{
bool operator()(Node const &a,Node const &b){
if(a.frequency == b.frequency)
return a.index > b.index;
return a.frequency > b.frequency;
}
};
class Solution
{
vector<Node> tree;
public:
void give_me_codes(Node *root,vector<string> &ans,string s,int &size){
cout<<"Printing s to show call: "<<s<<'\n';
/*while(root!=NULL){
cout<<root->index<<" "<<root->frequency<<"\n";
root=root->right;
root=root->left;
}*/
if(root==NULL){
return;
}
if(root->index<size)
ans.push_back(s);
if(root->left!=NULL)give_me_codes(root->left, ans,s+"0",size);
if(root->right!=NULL)give_me_codes(root->right,ans,s+"1",size);
}
vector<string> huffmanCodes(string S,vector<int> f,int N)
{
// Code here
priority_queue<Node, vector<Node>, comp> heap;
for(int i=0;i<N;++i){
Node element={.index=i,.frequency=f[i],.left=NULL,.right=NULL};
heap.push(element);
}
int sz = heap.size();
/*for(int i=0;i<sz;++i){
Node ele = heap.top();
heap.pop();
cout<<ele.index<<" "<<ele.frequency<<"\n";
}*/
Node *root;
int i=0;
while(heap.size()>1){
Node l = heap.top();heap.pop();
Node r =heap.top();heap.pop();
tree.push_back(l);
tree.push_back(r);
Node _new = {.index=sz++,.frequency=l.frequency+r.frequency,.left=&tree[i++],.right=&tree[i++]};
root =&_new;
heap.push(_new);
}
//cout<<tree[4].left<<" "<<tree[4].frequency<<'\n';
//cout<<tree[2].left<<" "<<tree[2].frequency<<'\n';
//tree[0].left=tree[0].right=NULL;
//tree[1].left=tree[1].left=NULL;
tree.push_back(*root);
vector<string> ans;
give_me_codes(root,ans,"",N);
cout<<'\n';
vector<string> v(N,"A");
return ans;
}
};
// { Driver Code Starts.
int main(){
int T;
cin >> T;
while(T--)
{
string S;
cin >> S;
int N = S.length();
vector<int> f(N);
for(int i=0;i<N;i++){
cin>>f[i];
}
Solution ob;
vector<string> ans = ob.huffmanCodes(S,f,N);
for(auto i: ans)
cout << i << " ";
cout << "\n";
}
return 0;
} // } Driver Code Ends
I tried assiging the left and right pointers of node 5 to NULL but it doesn't makes any difference and the output (when I print string s) stops after printing 110000 although I am expecting it to print 1100 and then probably move to the next node.
I shared the whole code and you can see what the output is showing. Can anyone please explain what is wrong here and what could be the possible fix?

Memory leak in C++ (Valgrind)

I implement the stack with a minimum. In this program, I get an error from valgrind. Something is wrong with the push() and main() functions. When I add delete st; to the push() function, I get even more errors. I check it through valgrind ./a.out. Sorry for the long code. I also wrote the rest of the functions for stack. But there is no error in them, I left those in the code where there may be an error.
#include <cstring>
#include <iostream>
struct Stack {
int data;
int min;
Stack* next;
};
void Push(Stack** top, int n) {
Stack* st = new Stack();
st->data = n;
if (*top == NULL) {
*top = st;
(**top).min = n;
} else {
st->min = ((n <= (**top).min) ? n : (**top).min);
st->next = *top;
*top = st;
}
std::cout << "ok" << std::endl;
}
void Pop(Stack** top) {
if (*top != NULL) {
std::cout << (**top).data << std::endl;
*top = (*top)->next;
} else {
std::cout << "error" << std::endl;
}
}
int main() {
Stack* top = nullptr;
int m;
std::cin >> m;
std::string str;
for (int i = 0; i < m; ++i) {
std::cin >> str;
if (str == "push") {
int value;
std::cin >> value;
Push(&top, value);
}
if (str == "pop") {
Pop(&top);
}
}
delete top;
}
When you just delete top, you destruct it (in your case it's nothing, but you can distract yourself for reading about destructors if interested) and free the dynamic memory allocated for top. However, you actually want to also delete top->next, top->next->next (if present) etc. A hotfix:
while (top) { // same as "while (top != nullptr) {"
Stack* next = top->next; // we can't use `top` after we `delete` it, save `next` beforehand
delete top;
top = next;
}
Now, about more general things. The course teaches you some really old C++ (almost just plain C; even C here is bad though). At the very least, your whole Push() can be replaced (thanks to lvalue references (Type&), std::min and aggregate initialization) with:
void push(Stack*& top, int n) {
top = new Stack{n, std::min(n, top ? top->min : n), top};
std::cout << "ok\n";
}
I'm new to C++ programming. I used to write in Python
Good job. Sadly, such teaching shows C++ as something too old and horrifying.
Edit
here's a new in Push, so there should most likely be a delete in Pop
That's right (thanks to #molbdnilo). You should delete popped elements instead of just leaking them.

Accessibility for Vectors of Singly Linked Lists (or possibly a Linked List of Linked Lists)

Been wracking my mind all day trying to hammer out the underlying data structures for a challenge assignment in one of my programming classes.
The problem is as follows:
Given an assortment of objects (each of which includes an identifier and a weight) and a supply of containers (which have a fixed weight capacity), pack all the items using as few containers as possible without overloading any of them.
I have the logic aspects hammered out using a hodgepodge of arrays, but the dynamic nature of this assignment has me wanting to optimize things by using vectors and/or linked lists.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <math.h>
#include <time.h>
#include <conio.h>
#include <vector>
#include <algorithm>
using namespace std;
struct Item
{
int number;
double weight;
bool operator < (const Item& str) const
{
return (weight < str.weight);
}
};
class Node
{
int number;
double weight;
Node* next;
public:
Node()
{};
void SetID(int iNum)
{
number = iNum;
};
void SetWeight(double iWeight)
{
weight = iWeight;
};
void SetNext(Node* iNext)
{
next = iNext;
}
int GetID()
{
return number;
};
double GetWeight()
{
return weight;
};
Node* Next()
{
return next;
};
};
class List
{
Node* head;
double weight;
public:
List()
{
head = NULL;
weight = 0;
};
int Size()
{
Node* tmp;
int count = 0;
for (tmp = head; tmp != NULL; tmp = tmp->Next())
{
count++;
}
return count;
};
double Weight()
{
return weight;
};
void Print()
{
Node *tmp = head;
if ( tmp == NULL )
{
cout << " E M P T Y" << endl;
return;
}
do
{
cout << setw(8) << tmp->GetID() << " | " << setw(8) << tmp->GetWeight() << endl;
tmp = tmp->Next();
} while ( tmp != NULL );
};
void Append(int iNum, double iWeight)
{
Node* newNode = new Node();
newNode->SetID(iNum);
newNode->SetWeight(iWeight);
newNode->SetNext(NULL);
Node *tmp = head;
if ( tmp != NULL )
{
while ( tmp->Next() != NULL )
{
tmp = tmp->Next();
}
tmp->SetNext(newNode);
}
else
{
head = newNode;
}
weight += iWeight;
};
};
double ItemWeights(vector<Item> iVect)
{
double total = 0;
for(int i = 0; i < iVect.size(); i++)
{
total += iVect[i].weight;
}
return total;
}
int main()
{
const double MAX_WEIGHT = 20;
vector< Item > source;
//
// Segment of code which propagates the vector data
// works fine, but is excluded for the sake of brevity
//
double totalWeight = ItemWeights(source);
// Duplicate vector of items
vector< Item > items(source);
for(int i = 0; i < items.size(); i++)
{
cout << setw(8) << items[i].number << setw(8) << items[i].weight << endl;
}
cout << "\n Total weight = " << totalWeight << endl;
cout << "\n\n Press any key to continue... ";
getch();
// Solution A-Original
// vector< vector< Item > > boxesAO( vector< Item >);
// boxesAO[0].push_back({items[items.size()].number, items[items.size()].weight});
vector< List > boxesAO;
// boxesAO[0].Append(items[items.size()].number, items[items.size()].weight);
return 0;
}
I've left some of the methods I've tried in the code (commented out) - none of which worked. As I mentioned above, I've got it working with arrays of linked lists and with 2D arrays, but the vast range of potential input makes these problematic at best. Either a bunch of empty lists taking up space or, worse, not having enough.
I'm thinking that vector< List > is my best option, but I can't figure out how I'm supposed to access any of the List functionality.
If someone would be so helpful as to offer a suggestion for how to create a "dynamic 2D array" as well as a code example of how to access it, I would be most greatly appreciative. My deepest thanks in advance.
EDIT:
#jaredad7 ~ That's what I've been trying, but it keeps causing the program to crash.
List box;
box.Append(items[items.size()].number, items[items.size()].weight);
This works just fine - no problems whatsoever.
The earlier code propagates a 1D vector of Item structs, which also works properly.
vector< List > boxes;
boxes[0].Append(items[items.size()].number, items[items.size()].weight);
This compiles fine but crashes during execution, no matter what index is used. (I'm also using couts for debugging, and the issue most definitely lies with trying to access the List functions.)
I'm suspecting that .push_back or somesuch may be needed, but I haven't been able to find much information concerning vectors of List objects.
If you can, my first suggestion would be to go with the vector (if that is allowed). As for accessing functions/attributes of a member of a vector, it's done the same way as an array, that is:
vectorname[i].functionname(a,b,c);
The best way to do this without vectors would be to use your nodes as the item container (a struct), and handle node-creation, deletion, etc. in your list class. Then, you would only really need one container for as many objects of one type as you need. You can make the type dynamic (although it appears you only need doubles for this project) by adding a class template (use google if you are unfamiliar with templates in C++). This will allow your user to make a container for each type of data (much like a vector).

Why this code failed to run

i want to generate a tree of siblings as under
ABCD
/ | \ \
A B C D
ABCD has four nodes i have taken a array for this *next[]. but this code does not run successfully but it produces the sequence. i have written code in main() which provide characters to the enque function. e.g. str.at(x) where x is variable in for loop.
struct node
{
string info;
struct node *next[];
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n);
void enqueue(string n)
{
node *p, *temp;
p=new node[sizeof(str.length())];
p->info=n;
for (int x=0;x<str.length();x++)
p->next[x]=NULL;
if(root==NULL)
{
root=p;
child=p;
}
else
{
cout<<" cl="<<cl<<endl;
if(cl<str.length())
{
child->next[cl]=p;
temp=child->next[cl];
cout<<"chile-info "<<temp->info<<endl;
}
else
cout<<" clif="<<cl<<endl;
}
}
OUTPUT
Enter String: sham
cl=0
chile-info s
cl=1
chile-info h
cl=2
chile-info a
cl=3
chile-info m
RUN FAILED (exit value 1, total time: 2s)
Firstly, where does "RUN FAILED" come from? Is that specific to your compiler?
Secondly, about the line p=new node[sizeof(str.length())];, it probably won't give you what you wanted because you're taking the sizeof of an unsigned integer ( which, depending on your platform is likely to give you 4 regardless of the string length. Which is not what you're after - you want the actual length of the string ).
So - since you're already using std::string, why not use std::vector? Your code would look a lot friendlier :-)
If I take the first couple of lines as your desired output ( sorry, the code you posted is very hard to decipher, and I don't think it compiles either, so I'm ignoring it ;-) )
Would something like this work better for you?
#include <iostream>
#include <vector>
#include <string>
typedef struct node
{
std::string info;
std::vector<struct node*> children;
}Node;
Node * enqueue(std::string str)
{
Node * root;
root = new Node();
root->info = str;
for (int x = 0; x < str.length(); x++)
{
Node * temp = new Node();
temp->info = str[x];
root->children.push_back(temp);
}
return root;
}
int main()
{
Node * myRoot = enqueue("ABCD");
std::cout << myRoot->info << "\n";
for( int i = 0; i < myRoot->children.size(); i++)
{
std::cout << myRoot->children[i]->info << ", ";
}
char c;
std::cin >> c;
return 0;
}
Your code seems not full.
At least the line
p=new node[sizeof(str.length())];
seems wrong.
I guess enqueue should be something similar to the following:
struct node
{
string info;
struct node *next; // [] - is not necessary here
}*root,*child;
string str, goal;
int dept=0,bnod=0,cl,z=0;
void enqueue(string n)
{
node *p, *temp;
p = new node;
p->next = new node[str.length()];
p->info=n;
for (int x=0;x<str.length();x++)
{
p->next[x] = new node;
p->next[x]->next = 0;
p->next[x]->info = str[x];
}
if(root==NULL)
{
root=p;
child=p;
}
}
Please provide more info to give a more correct answer