The question is
There is a collection of input strings and a collection of query strings. For each query string, determine how many times it occurs in the list of input strings.
strings = [ab,ab,abc]
queries = [ab,abc,bc]
There are instances 2 of ab, 1 of 'abc' and 0 of 'bc'. For each query, add an element.
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
struct node {
int data;
node *next;
}*first=NULL,*last= new node;
void create(int count) {
node *temp;
temp = new node;
temp->data = count;
temp->next = NULL;
if(!first) first=last=temp;
else {
last->next = temp;
last = temp;
}
}
void display() {
node *temp = first;
while(temp) {
cout<<temp->data<<endl;
temp = temp->next;
}
}
void matchStrings(string s[],string q[],int s_count,int q_count){
int counter;
// res = new int[q_count];
for(int i=0;i<=q_count;i++){
counter = 0;
for(int j=0;j<s_count;j++){
if( q[i] == s[j] ) counter++;
}
if(counter != 0) create(counter);
else create(0);
}
// return res;
}
int main() {
int string_count,query_count,*res;
cin>>string_count;
string strings[string_count];
for(int i=0;i<string_count;i++) cin>>strings[i];
cin>>query_count;
string queries[query_count];
for(int i=0;i<query_count;i++) cin>>queries[i];
matchStrings(strings,queries,string_count,query_count);
// res = matchStrings(strings,queries,string_count,query_count);
matchStrings(strings,queries,string_count,query_count);
// for(int i=0;i<query_count;i++) cout<<res[i]<<endl;
display();
return 0;
}
Now I am trying to implement it using Linked List but instead of getting output as 2,1,0.
I am getting output as 2,1,0,2,2,1,0,2.
I dont how is the LL being created for more than 3 links.
Please help.
In the function void matchStrings(),
you have written
for(int i=0;i<=q_count;i++){
Rather it should be
for(int i=0;i<q_count;i++){
Because of the extra iteration, a randomly generated string gets checked with the set of strings[], and as a result they are incorrectly matched.
So this leads to the execution of create(0) one extra time, which results in creating an extra node with data 0, that gets printed.
Related
I write a code for insertion sort for integer data in linked list in c++, I referred to the algorithms on the Internet, and finally took the following code using array as a basic concept for my version.
however, the sorting always ignore my first element,(but all the other element is ordered well).
I have tried checking my loop statement, checking the pointer address while looping (because my key pointer loop at first time didn't go into the judge pointer loop), checking the shifting mechanism while comparing, but I cannot find my logic problem.
(I know someone would said I doesn't provide enough data for you to help me, but I have been checking these things for two days, including asking friends and searching the solutions existed on website. So I really hope someone can answer me without blame, thank you.)
array version(on the internet)
#include <iostream>
void InsertionSort(int *arr, int size){
for (int i = 1; i < size; i++) {
int key = arr[i];
int j = i - 1;
while (key < arr[j] && j >= 0) {
arr[j+1] = arr[j];
j--;
}
arr[j+1] = key;
}
}
linked list version(by my own)
Node class used in my version
class Node
{
public:
Node()
{
next = NULL;
pre = NULL;
}
Node(int n)
{
data = n;
next = NULL;
pre = NULL;
}
int getData() { return data; }
Node *getNext() { return next; }
Node *getPre() { return pre; }
void setData(int d) { data = d; }
void setNext(Node *n) { next = n; }
void setPre(Node *p) { pre = p; }
private:
int data;
Node *next, *pre;
};
class List
{
public:
List() { list = NULL; }
List(int n) { generate(n); }
void generate(int n)
{
int j;
list = NULL;
for(j = 0;j < n;j ++)
generate();
}
void generate()
{
Node *buf = new Node(rand());
buf->setNext(list); //list->NODE2.next->NODE1.next->NULL
if(list != NULL)
list->setPre(buf);
list = buf;
}
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;// judge is the value that is going to compare with key
int key;
for(keyptr = list->getNext(); keyptr != NULL;
keyptr = keyptr->getNext()){
//if we set list as 5,7,6 ; 6 is key
key = keyptr->getData();//store the key value for the setting after shifting
breakByCompare = 0;
for(judgeptr = keyptr->getPre() ; judgeptr->getPre()!= NULL;
judgeptr= judgeptr->getPre()){
//list: 5,7,6 ; 7 is judge
if(judgeptr->getData() > key){
// 7>6, so we shift 7 to the position which was for 6
judgeptr->getNext()->setData(judgeptr->getData());// list: 5,7,7 ;
cout << judgeptr->getData() << " , " << keyptr->getData() << endl;
}
else{
break;
}
}
judgeptr->getNext()->setData(key);// list: 5,6,7
}
}
void print()
{
Node *cur = list;
while(cur != NULL)
{
cout<<cur->getData()<<" ";
cur = cur->getNext();
}
cout<<endl;
}
private:
Node *list;
};
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#define SIZE 100
int main()
{
srand(time(NULL));
List *l = new List(10);
l->print();
l->insertionSort();
l->print();
}
One of the most important difference between a linked list and an array is that it is sometimes required to handle the first element as a special case.
Here is a fixed version of your sorting method :
void insertionSort()
{
bool breakByCompare;
Node* keyptr;
Node* judgeptr;
int key;
for(keyptr = list->getNext(); keyptr != NULL; keyptr = keyptr->getNext()){
key = keyptr->getData();
breakByCompare = 0;
// I replaced judgeptr->getPre() by judgeptr in the condition
// to allow the backward loop to go until the root
for(judgeptr = keyptr->getPre() ; judgeptr != NULL; judgeptr= judgeptr->getPre()){
if(judgeptr->getData() > key){
judgeptr->getNext()->setData(judgeptr->getData());
cout << judgeptr->getData() << " , " << key << endl;
}
else break;
}
// Here is the special case : we must support a null judgeptr
// and replace its next element by the list
if (judgeptr) judgeptr->getNext()->setData(key);
else list->setData(key);
}
}
I had to implement a Linked HashTable for a project. Now I have to come up with an excercise and a solution to it using my hashtable. Everything works just fine, except I get random Segfault errors.
By Random I mean: It is the same line of code that causes it, but always at different times, calls.
I tested my code in Atom, Codeblocks and in Visual Studio Code. Both Atom and CB threw SegFault error, but VS Code ran it just fine without a problem.
NOTE: THIS IS NOT THE FULL/REAL CODE. It's part of a header file that is included in the main.cpp file which is then compiled and ran.
The Code:
#include <iostream>
#include <typeinfo>
#include <string>
using namespace std;
//List:
template<class T>
struct Node
{
string data;
Node *next;
};
class List
{
private:
Node *head, *tail;
int length;
friend class HashTable;
public:
List();
List(const List &L);
//~List() {delete this;};
List& operator =(List L);
int find(string);
void insert(string value);
void remove_head();
void remove_poz(int);
void remove_tail();
void clear();
void display();
};
List::List()
{
head = NULL;
tail = NULL;
length = 0;
}
template<>
string List<string>::findByIndex(int ind)
{
int i = 0;
Node<string>* temp = new Node<string>;
temp = head;
while (temp != NULL)
{
i++;
if (i == ind) return temp->data;
temp = temp->next;
}
delete temp;
return "-1";
}
template<class T>
void List<T>::remove_head()
{
Node<T>* temp = new Node<T>;
temp = head;
head = head->next;
delete temp;
length--;
}
template<class T>
void List<T>::remove_pos(int pos)
{
int i;
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
for (i = 1; i < pos; ++i)
{
prev = curr;
curr = curr->next;
}
if (curr)
{
prev->next = curr->next;
length--;
}
else cout << "Error" << endl;
}
template<class T>
void List<T>::remove_tail()
{
Node<T>* curr = new Node<T>;
Node<T>* prev = new Node<T>;
curr = head;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
tail = prev;
prev->next = NULL;
delete curr;
length--;
}
//HashTable:
class HashTable
{
private:
List *table;
float load, stored;
int slots;
friend class List;
public:
HashTable();
HashTable(int);
~HashTable();
int hashFunc(string key);
int findTable(string);
int findList(string);
HashTable& operator =(const HashTable&);
void resize(); //I need this one
void insert(string);
void remove(string);
void clear(int);
void clear();
void display();
};
HashTable::HashTable()
{
stored = 0;
load = 0.00;
slots = 15;
table = new List[slots];
}
int HashTable::hashFunc(string key)
{
int g, h = 0;
unsigned int i;
for (i = 0; i < key.size(); ++i)
{
h = (h << 4) + (int)(key[i]);
g = h & 0xF0000000L;
if (g != 0)
{
h = h ^ (g >> 24);
}
h = h & ~g;
}
return h % slots;
}
template<class T>
void HashTable<T>::remove(T value)
{
int ind = hashFunc(value);
int findInd = table[ind].findByValue(value);
if (findInd == 0)
table[ind].remove_head();
else if (findInd < table[ind].length)
table[ind].remove_pos(findInd);
else table[ind].remove_tail();
if (table[ind].isEmpty()) occupied--;
stored--;
load = stored / slots;
}
The function that would cause the segfault:
(This would be called over and over again in a loop till I don't have more elements in my table)
string reakcio(HashTable<string>& HT, int tarolok)
{
const int anyagszam = rand() % 4 + 2; //Min 2, Max 5 anyag hasznalodik
int i = 0, j;
string anyagok[5];
string eredmeny;
for(j = 0; j < tarolok && i < anyagszam; ++j) //elemek kivetele
{
while(!HT.table[j].isEmpty())
{
anyagok[i++] = HT.table[j].findByIndex(1); //This line right here is the culprit :(
HT.remove(anyagok[i-1]);
}
}
const int siker = rand() % 4 + 0; //75% esely a sikerre
if (siker)
{
eredmeny = anyagok[0];
for(i = 1; i < anyagszam; ++i)
eredmeny += " + " + anyagok[i];
}
else
eredmeny = "Sikertelen reakcio";
return eredmeny;
}
(Note: only the functions that might be needed are shown here)
Every element of my hashtable, or of my lists is a 10 character long random string value.
srand(time(NULL)) is used before the function call in main.cpp
Any help or advice would be much appreciated, as I'm stuck at this and I really need to move on to the next portion of my exercise, but I can't without this.
The main.cpp file:
#include <iostream>
//#include "LinkedHash.h"
#include "functions.cpp"
int main()
{
HashTable<string> Anyagok;
int tarolok;
tarol(Anyagok); //Stores the data from file, no problem here, functions.cpp
tarolok = Anyagok.getSlots();
srand(time(NULL));
int i = 1;
while (Anyagok.getStored() > 5 )
cout<<reakcio(Anyagok, tarolok)<<" "<<i++<<endl;
return 0;
}
The LinkedHash.h contains the hashtable and the list, the functions.cpp contains the problematic function.
EDIT:
By suggestion I changed out the
Node<string>* temp = new Node<string>;
temp = head;
part to
Node<string>* temp = head;
Also removed the delete line.
But my problem is still the same :/
Everything works just fine, except I get random Segfault errors
Then nothing works at all.
A first review show little care to the cornercases in the list class. You need to define a correct behavior for
operation on empty lists
operation on first and last element
key not found during search
Notable errors found:
remove_head, remove_tail will segfault on empty list. head is NULL. head->next is invalid memory access. Similar errors are all over the implementation.
HashTable<T>::remove(T value) will always remove something. Even if the value argument is not in the hashtable. This is deeply flawed
findByIndex returning "-1" make no sense. "-1" is a valid input.
Node<T>* temp = new Node<T>;temp = head;. You just leaked memory. You need a pointer to manipulate node addresses. You should not instantiate Nodes to get a pointer. This is not an issue (ie not noticeable) for a small projet, but unacceptable for a real implementation.
I am creating a trie and am having trouble at the time of compiling.
The warningI get is:
"Reading invalid data from 'currNode->dict': the readable size is '104' bytes, but '388' bytes may be read."
#pragma once
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
const int SIZE = 26;
struct Node {
bool isWord;
Node* dict[SIZE];
};
class Dictionary
{
public:
Dictionary();
Dictionary(string file);
void addWord(string word);
private:
Node *root;
int numWords;
};
Dictionary::Dictionary()
{
numWords = 0;
root = new Node;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
}
Dictionary::Dictionary(string file)
{
numWords = 0;
root = new Node;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
ifstream inFile;
string word;
inFile.open(file);
while (inFile >> word) {
addWord(word);
numWords++;
}
}
void Dictionary::addWord(string word)
{
int len = word.length(); // size of word
char letter;
int pos;
Node *currNode = root;
for (int i = 0; i < len; i++) {
letter = word[i]; // takes character at position i
pos = letter - 'a'; // finds the position of the character in the array (0 through 25)
// with 'a' being 0 and 'z' being 25
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node;
currNode->isWord = false;
}
currNode = currNode->dict[pos];
}
currNode->isWord = true;
}
What could be causing this? I'm pretty sure that I'm not trying to access invalid memory. Perhaps it's the way I setup my node and class?
One mistake is that you fail to initialize Node to default values. In your Dictionary default constructor, you have code that really should be part of what Node should be doing:
root = new Node ;
for (int i = 0; i < SIZE; i++)
root->dict[i] = nullptr;
This should be Node's job, not the job of Dictionary.
Instead, you have this:
struct Node {
bool isWord;
Node* dict[SIZE];
};
So every time you do this:
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node;
You are creating an uninitialized Node object. That entire Node::dict array contains uninitialized pointers, which you later try to access.
The easiest solution is to zero-initialize the Node object.
if (!currNode->dict[pos]) {
currNode->dict[pos] = new Node(); // <-- Note the parentheses
This will automatically set the dict pointers to nullptr.
The other method is to make sure Node objects are created with default values:
#include <algorithm>
struct Node {
bool isWord;
Node* dict[SIZE];
Node() : isWord(false) { std::fill_n(dict, SIZE, nullptr); }
};
With this, even new Node; will create nodes that are initialized.
I'm trying to make a stack of hash tables. The stack is meant to hold the hash tables. I want to have a stack (in this case List) of hash tables. Is there someway to put H1 and H2 into my List One? I'm planning to a make pop() and push() function for the stack of hash tables once I'm able to accomplish this. I'm also not allowed to use STL code on this program.
I may be overthinking something or missing something important. I'm not really sure if I'm going about it the right way. I've been trying to figure it out, but I'm lost. I'm pretty fresh to all of this. I'd really enjoy a resolution for issue, thank you.
List.h
#include "Hashtable.h"
#ifndef LIST_H
#define LIST_H
class List
{
private:
typedef struct node
{
//stores the data in each node
int data;
//this creates a node pointer to point to another node in the list
node* next;
}*nodePtr;
//the code above simplifies the code in the comment below
//The code below code allows you to type "nodePtr"
//instead of node* to make node
//typedef struct node* nodePtr;
nodePtr head;
nodePtr curr;
nodePtr temp;
//functions in public access and manipulate the private section
//you don't actually access the private section
public:
//constructor sets default values for our values: head, curr, and temp
//putting the class name here let's the program know that we will set those
//values when the list is created.
List();//constructor
//"void" so it returns no data
void AddNode(int addData);
//whatever value we pass through delData,
//the DeleteNode will fgo through the list and search for data that matches
//it and delete the node.
void DeleteNode(int delData);
void PrintList();
};
#endif /* LIST_H */
List.cpp
#include <iostream>
#include <cassert>
#include <iomanip>
#include <cstdlib>
#include "List.h"
using namespace std;
//now here you define the function from the class
//start out with class name "::" then the things you want to define from List.h
List::List()
{
//values from Link.h
head = NULL;
curr = NULL;
temp = NULL;
}
void List::AddNode(int addData)
{
nodePtr n = new node;
//creating a new node pointer called "n" and a new node.
// our new node pointer points to new node
n->next = NULL;
//find the node n is pointing to access it's next element and make
//that point to nothing
n->data = addData;
if(head != NULL)
{
//make the current pointer point to head(front of the list)
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
//if it's not at the end of the list it will exit the while loop
//and point to "n" or the new node
curr->next = n;
}
else
{
//if we don't have a list,the new node will be the front of the list.
head = n;
}
}
void List::DeleteNode(int delData)
{
//now delPtr is the deletion pointer and points to nothing to start with
nodePtr delPtr = NULL;
temp = head;
curr = head;
//while the current node isn't at the end of the list and isn't the data
//that needs to be deleted
while(curr != NULL && curr->data != delData)
{
temp = curr;
curr = curr->next;
}
if(curr == NULL)
{
//if we reach the end of the list
cout << delData << " was not in the list \n";
delete delPtr;
}
else
{
delPtr = curr;
curr = curr->next;
temp->next = curr;
if(delPtr == head)
{
head = head->next;
temp = NULL;
}
delete delPtr;
cout << "The value " << delData << " was deleted \n";
}
}
void List::PrintList()
{
curr = head;
while(curr != NULL)
{
cout << curr->data << endl;
curr = curr->next;
//it'll keep moving to the next node until the end of the list
}
}
Hashtable.h Also, name is the data of the items placed in the hash table.
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
#ifndef HASHTABLE_H
#define HASHTABLE_H
class HashTable
{
private:
static const int tableSize = 10;
//everything in the braces are what makes the item
struct obj
{
int name;
obj* next;
};
obj* HASHTBL[tableSize];
public:
HashTable();
//Hash is the function represents where in the hash table
//we will store the key
//take a string stored in variable
int Hash( int key);
void AddObj(int name);
int ItemsinBucket(int index);
void PrintTable();
};
#endif /* HASHTABLE_H */
Hashtable.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include "HashTable.h"
using namespace std;
//Takes from the HashTable class in HashTable.h
HashTable::HashTable()
{
for(int x = 0; x < tableSize; x++)
{
HASHTBL[x] = new obj;
HASHTBL[x]->name = NULL;
HASHTBL[x]->next = NULL;
}
}
void HashTable::AddObj( int name)
{
int index = Hash(name);
if(HASHTBL[index]->name == NULL)
{
HASHTBL[index]->name = name;
}
else
{
obj* Ptr = HASHTBL[index];
obj* n = new obj;
n->name = name;
n->next = NULL;
while(Ptr->next !=NULL)
{
Ptr = Ptr->next;
}
Ptr->next = n;
}
}
int HashTable::ItemsinBucket(int index)
{
int count = 0;
if (HASHTBL[index]->name == NULL)
{
return count;
}
else
{
count++;
obj* Ptr = HASHTBL[index];
while(Ptr->next != NULL)
{
count++;
Ptr = Ptr->next;
}
}
return count;
}
void HashTable::PrintTable()
{
int number;
for(int x = 0; x< tableSize; x++)
{
number = ItemsinBucket(x);
cout << "------------------------\n";
cout << "index = " << x << endl;
cout << HASHTBL[x]->name << endl;
cout << "The num of items in index = "<< number << endl;
cout << "------------------------\n";
}
}
int HashTable::Hash(int key)
{
//defining HashTable function:
int HashTable = 0;
int index;
//will return integer value...or length of string you pass in
for(int x = 0; x < key-1; x++)
{
HashTable = HashTable + x;
}
//so the hash table will take a number and mod it to return the remainder
//the remainder is the index
index = HashTable % tableSize;
return index;
}
And, finally, main.cpp. The two hashtables are the tests H1 and H2. The List One is meant to be the stack the two hash tables go into.
#include <iostream>
#include <cassert>
#include <iomanip>
#include <cstdlib>
#include "List.h"
#include "Hashtable.h"
using namespace std;
int main(int argc, char** argv)
{
List One;
One.AddNode(3);
One.AddNode(5);
One.AddNode(7);
One.PrintList();
One.DeleteNode(3);
One.PrintList();
HashTable H1;
H1.AddObj(4);
H1.AddObj(23);
H1.AddObj(200);
H1.AddObj(10);
H1.AddObj(15);
H1.AddObj(42);
H1.AddObj(33);
H1.AddObj(44);
H1.AddObj(55);
H1.AddObj(5);
H1.AddObj(9);
H1.AddObj(90);
H1.PrintTable();
HashTable H2;
H2.AddObj(10);
H2.AddObj(90);
H2.AddObj(99);
H2.AddObj(34);
H2.AddObj(88);
H2.AddObj(14);
H2.AddObj(87);
H2.AddObj(18);
H2.AddObj(54);
H2.AddObj(56);
H2.AddObj(6);
H2.AddObj(2);
}
This is the output. The top is the test of the list and a test of the DeleteNode function.
3
5
7
The value 3 was deleted
5
7
------------------------
index = 0
42
The num of items in index = 1
------------------------
------------------------
index = 1
23
The num of items in index = 4
------------------------
------------------------
index = 2
0
The num of items in index = 0
------------------------
------------------------
index = 3
4
The num of items in index = 2
------------------------
------------------------
index = 4
0
The num of items in index = 0
------------------------
------------------------
index = 5
0
The num of items in index = 0
------------------------
------------------------
index = 6
10
The num of items in index = 4
------------------------
------------------------
index = 7
0
The num of items in index = 0
------------------------
------------------------
index = 8
9
The num of items in index = 1
------------------------
------------------------
index = 9
0
The num of items in index = 0
------------------------
I have been given the task to receive a string input from the user and reverse the order of the string and print the result out. My code is this:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main() {
string input;
char *head = new char, *tail = new char;
char temp;
//Get the string from the user that will be reversed
cout << "Enter in a string that you want reversed: ";
getline(cin, input);
//Create and copy the string into a character array
char arr[input.length()];
strcpy(arr, input.c_str());
//Set the points of head/tail to the front/back of array, respectably
head = &arr[0]; tail = &arr[input.length()-1];
//Actual reversal part of the code (Does not work)
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
//Print the character array
for(int i=0; i<input.length(); i++) {
cout << arr[i];
}
//Free up memory
delete head; delete tail;
head = NULL; tail = NULL;
return 0;
}
When I print it, literally nothing has been changed and I can't seem to understand why as I'm brand new to pointers. This is the specific block that I'm having trouble with:
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
Any input on how to fix this or pointer knowledge in general that'd help is greatly appreciated.
Your approach is good but...
for(int i=0; i<input.length(); i++) {
temp = *(tail);
*tail = *head;
*head = temp;
tail --; head ++;
}
Didn't you try working this out on paper? You swap each pair of letters twice, bringing the array back to its original order.
Just change the limit of iteration, to stop when head and tail meet in the middle, and you'll be all right:
for(int i=0; i<input.length()/2; i++) {
...
}