VS Code not showing local variables at all - c++

I am using VS code for coding in C++. The problem arises when I try to debug a code and set a breakpoint. The local variables pane doesn't show any variables at all. Sometimes it does show some variables but not all of them.
Also when I try to close the debugger and click on the stop button, it does not stop. It requires me to click on it multiple times, which I think means, that multiple debuggers are opened or something like that.
To reproduce this problem, save this text as input_static.txt.
T1 1 2 5
T2 2 4
T3 2 3
T4 1 2 4
T5 1 3
T6 2 3
T7 1 3
T8 1 2 3 5
T9 1 2 3
And debug the following code by setting a breakpoint at line number 201.
#include <bits/stdc++.h>
using namespace std;
ifstream fin;
ofstream fout;
typedef struct fptnode
{
int item, count;
fptnode *next;
map<int, fptnode *> children;
fptnode *parent;
fptnode(int item, int count, fptnode *parent)
{
this->item = item;
this->count = count;
this->parent = parent;
}
} * FPTPTR;
map<int, int> frequency;
bool isMoreFrequent(int a, int b)
{
if (frequency[a] == frequency[b])
return a < b;
return frequency[a] > frequency[b];
}
class FPTREE
{
public:
FPTPTR root;
map<int, list<FPTPTR>> headers;
// map<int, int> frequency;
FPTREE()
{
this->root = new fptnode(-1, 0, NULL);
}
// class isMoreFrequent
// {
// public:
// FPTREE *T;
// isMoreFrequent(FPTREE *T)
// {
// this->T = T;
// }
// bool operator()(int item1, int item2)
// {
// return T->frequency[item1] > T->frequency[item2];
// }
// };
FPTPTR getNewNode(int item, int count, fptnode *parent)
{
FPTPTR T = new fptnode(item, count, parent);
this->headers[item].push_back(T);
return T;
}
void add(vector<int> &transaction)
{
stack<int> S;
std::sort(transaction.begin(), transaction.end(), isMoreFrequent);
for (int i = transaction.size() - 1; i >= 0; i--)
{
S.push(transaction[i]);
}
insert(root, S);
}
int insert(FPTPTR T, stack<int> &S)
{
T->count++;
if (S.empty())
return 0;
int top = S.top();
S.pop();
if (T->children[top] == NULL)
{
T->children[top] = getNewNode(top, 0, T);
}
insert(T->children[top], S);
return 0;
}
void printPreOrder(ofstream &fout)
{
printPreOrder(fout, this->root);
}
void printPreOrder(ofstream &fout, FPTPTR T)
{
if (T)
{
fout << "[" << T->item << ", " << T->count << "]" << ' ';
for (auto p : T->children)
{
printPreOrder(fout, p.second);
}
}
}
void printTree(ofstream &fout)
{
printTree(fout, this->root);
}
void printTree(ofstream &fout, FPTPTR T, int level = 0)
{
if (T)
{
for (int i = 0; i < level; i++)
fout << "\t";
fout << "[" << T->item << ", " << T->count << "]" << endl;
for (auto p : T->children)
{
printTree(fout, p.second, level + 1);
}
}
}
void generatePath(FPTPTR node, vector<int> &path)
{
if (node && node->item >= 0)
{
path.push_back(node->item);
generatePath(node->parent, path);
}
}
FPTREE newTree(int item)
{
list<FPTPTR> &nodes = this->headers[item];
vector<int> patternBase;
FPTREE f;
for (auto node : nodes)
{
patternBase.clear();
generatePath(node->parent, patternBase);
for (int j = 0; j < node->count; ++j)
f.add(patternBase);
}
return f;
}
int clear()
{
return this->clear(this->root);
}
int clear(FPTPTR T)
{
for (auto p : T->children)
{
clear(p.second);
}
return 0;
}
bool isEmpty()
{
// return this->root->count == 0;
return this->root->children.empty();
}
} F;
ofstream tempout;
map<set<int>, int> mine(FPTREE f, int r = -1)
{
map<set<int>, int> M;
if (!f.isEmpty())
{
// if (f.root->children.empty())
// M[{}] += f.root->count;
tempout << "\nOn removing " << r << ":\n";
f.printTree(tempout);
for (auto p : frequency)
{
FPTREE subF = f.newTree(p.first);
map<set<int>, int> m = mine(subF, p.first);
for (auto q : m)
{
auto itemset = q.first;
itemset.insert(p.first);
M[itemset] += q.second;
}
subF.clear();
}
return M;
}
// tempout << "\nTerminated.\n";
return {};
}
int main(int argc, char const *argv[])
{
fin.open("input_static.txt");
fout.open("output_static.txt");
tempout.open("temp");
string str, s;
while (fin >> s)
{
if (s.front() != 'T')
{
frequency[stoi(s)]++;
}
}
vector<int> transaction;
stringstream st;
fin.clear();
fin.seekg(0);
while (std::getline(fin, str))
{
st.clear();
st.str(str);
transaction.clear();
while (st >> s)
{
if (s.front() != 'T')
{
transaction.push_back(stoi(s));
}
}
F.add(transaction);
}
fout << "Preorder:\n";
F.printPreOrder(fout);
fout << endl
<< endl;
fout << "Tree in directory form:\n";
F.printTree(fout);
// printPrefixes(5);
map<set<int>, int> frequentItemsets = mine(F);
fout << endl;
for (auto p : frequentItemsets)
{
fout << "Frequency=" << p.second << "\t";
for (int item : p.first)
{
fout << item << ' ';
}
fout << endl;
}
// for (int i = 1; i <= 5; ++i)
// {
// fout << i << ":\n";
// FPTREE f = F.newTree(i);
// f.printTree();
// }
// F.newTree(1).newTree(2).printTree(fout);
return 0;
}
If it helps this is a program to generate and mine an FP-tree to find frequent itemsets in a transactional database.

Related

vector assign issue in template of c++

I am writing a program to implement queue using vectors. I am using the class as template. And in main function am trying to create both string vector and int vector based on template data type. However am getting compilation error from vector assign method.
template <class T>
class queueWithArray {
private:
vector<T> queueArray;
int numberOfElements;
int size;
int head;
int tail;
public:
queueWithArray(int n) {
numberOfElements = 0;
head = -1;
tail = -1;
size = n;
if(is_same<T,string>::value) {
cout << "data type is string" << endl;
queueArray.assign(n,"");
} else {
queueArray.assign(n,0);
}
}
...
int main() {
string InputArray[] = {"to", "be", "or", "not", "to", "-", "be", "-", "-", "that", "-", "-", "-", "is"};
queueWithArray<string> obj(2);
for(auto i=0; i < (signed int)(sizeof(InputArray)/sizeof(InputArray[0])); ++i) {
if(InputArray[i] == "-") {
string item = obj.dequeue();
cout << "dequeue->" << item << endl;
} else {
obj.enqueue(InputArray[i]);
cout << "enqueue->" << InputArray[i] << endl;
}
obj.printQueue();
}
int InputArray_int[] = {10,20,30,40,50,-1,20,-1,-1,60,-1,-1,-1,70};
queueWithArray<int> obj_int(2);
for(auto i=0; i < (signed int)(sizeof(InputArray_int)/sizeof(InputArray_int[0])); ++i) {
if(InputArray_int[i] == -1) {
int item = obj_int.dequeue();
cout << "dequeue->" << item << endl;
} else {
obj_int.enqueue(InputArray_int[i]);
cout << "enquque->" << InputArray_int[i] << endl;
}
obj.printQueue();
}
return 0;
}
..\QueueUsingTemplate.cpp:135:31: required from here
..\QueueUsingTemplate.cpp:45:4: error: no matching function for call to >'std::vector::assign(int&, const char [1])'
queueArray.assign(n,"");
^~~~~~~~~~
In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\vector:64:0,
from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\queue:61,
from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\mingw32\bits\stdc++.h:86,
from ..\QueueUsingTemplate.cpp:18:
c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\bits\stl_vector.h:489:7: note: candidate: void >std::vector<_Tp, _Alloc>::assign(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with >_Tp = int; _Alloc = std::allocator; std::vector<_Tp, _Alloc>::size_type = unsigned int; >std::vector<_Tp, _Alloc>::value_type = int]
assign(size_type __n, const value_type& __val)
^~~~~~
Thank you so much VainMan. queryArray.assign(n, T{}); solves the issue. Hi Louis, please find the complete program with include statements here.
/*
* queueUsingArray.cpp
*
* Created on: 02-Nov-2021
* Author: Admin
*/
#include <iostream>
#include <ctype.h>
#include <bits/stdc++.h>
#include <vector>
#include <typeinfo>
#include <type_traits>
using namespace std;
template <class T>
class queueWithArray {
private:
vector<T> queueArray;
int numberOfElements;
int size;
int head;
int tail;
public:
queueWithArray(int n) {
numberOfElements = 0;
head = -1;
tail = -1;
size = n;
queueArray.assign(n,T{});
}
void enqueue(T item) {
if(numberOfElements == size) {
resize(size * 2);
}
if((head == -1) && (tail == -1)) {
head = tail = 0;
} else {
tail = (tail + 1) % size;
}
queueArray[tail] = item;
numberOfElements++;
}
T dequeue() {
T item;
if(numberOfElements == 0) {
cout << "No elements to dequeue" << endl;
} else {
if(numberOfElements == size/4) {
resize(size/2);
}
item = queueArray[head];
if(head == tail) {
head = tail = -1;
} else {
head = (head + 1) % size;
}
numberOfElements--;
}
return item;
}
bool isEmpty() {
return ((head == -1) && (tail == -1));
}
void resize(int newSize) {
if(newSize > 0) {
size = newSize;
int newIndex = 0;
for(int i=head; i<=tail; ++i){
queueArray[newIndex] = queueArray[i];
newIndex++;
}
queueArray.resize(newSize);
head=0;
tail=newIndex-1;
} else {
return;
}
}
void printQueue() {
if(!isEmpty()) {
for(auto i=head; i<tail; i++) {
cout << queueArray[i] << "->";
}
cout << queueArray[tail] << endl;
} else {
cout << "Queue is Empty" << endl;
}
}
};
int main() {
string InputArray[] = {"to", "be", "or", "not", "to", "-", "be", "-", "-", "that", "-", "-", "-", "is"};
queueWithArray<string> obj(2);
for(auto i=0; i < (signed int)(sizeof(InputArray)/sizeof(InputArray[0])); ++i) {
if(InputArray[i] == "-") {
string item = obj.dequeue();
cout << "dequeue->" << item << endl;
} else {
obj.enqueue(InputArray[i]);
cout << "enqueue->" << InputArray[i] << endl;
}
obj.printQueue();
}
int InputArray_int[] = {10,20,30,40,50,-1,20,-1,-1,60,-1,-1,-1,70};
queueWithArray<int> obj_int(2);
for(auto i=0; i < (signed int)(sizeof(InputArray_int)/sizeof(InputArray_int[0])); ++i) {
if(InputArray_int[i] == -1) {
int item = obj_int.dequeue();
cout << "dequeue->" << item << endl;
} else {
obj_int.enqueue(InputArray_int[i]);
cout << "enquque->" << InputArray_int[i] << endl;
}
obj_int.printQueue();
}
return 0;
}

How to calculate word frequency in a list using C++?

So I have some words in a file. I read them to a List then I'm trying to find the frequency of each word. My problem is that I have to follow a certain implementation for the list which isn't very flexible.
Here's the List class:
const int maxListSize = 50;
template<class T>
class List {
private:
int numberOfElements;
int currentPosition;
T data[maxListSize];
public:
List() {
numberOfElements = 0;
currentPosition = -1;
}
void insert(T element) {
if (numberOfElements >= maxListSize) {
cout << "List is Full" << endl;
return;
}
data[numberOfElements] = element;
numberOfElements++;
}
bool first(T &element) {
if (numberOfElements == 0) {
cout << "List is Empty" << endl;
return false;
}
else {
currentPosition = 0;
element = data[currentPosition];
return true;
}
}
bool next(T &element) {
//Check if the user called the first function
if (currentPosition < 0) {
cout << "Please call the first function before calling the next" << endl;
return false;
}
if (currentPosition >= numberOfElements - 1) {
//cout << "No next item" << endl;
return false;
}
currentPosition++;
element = data[currentPosition];
return true;
}
};
Assume my list is called names. How can I get the frequency of each word?
Here is how I would do it, given the unfortunate interface of List.
Initially I thought I would use List<pair<string, int>> but the first and next functions provide a copy of the element making it impossible to modify in place, so pointers it is!
This leaks memory. If not leaking is important to you then you could use smart pointers or attempt to free the memory. I figured simple might be better.
#include <iostream>
#include <string>
const int maxListSize = 50;
template<class T>
class List
{
private:
int numberOfElements;
int currentPosition;
T data[maxListSize];
public:
List()
{
numberOfElements = 0;
currentPosition = -1;
}
void insert(T element)
{
if (numberOfElements >= maxListSize)
{
return;
}
data[numberOfElements] = element;
numberOfElements++;
}
bool first(T &element)
{
if (numberOfElements == 0)
{
return false;
}
else
{
currentPosition = 0;
element = data[currentPosition];
return true;
}
}
bool next(T &element)
{
if (currentPosition < 0)
{
return false;
}
if (currentPosition >= numberOfElements - 1)
{
return false;
}
currentPosition++;
element = data[currentPosition];
return true;
}
};
using WordPair = std::pair<std::string, int>;
using WordList = List<WordPair*>;
void incrementCount(WordList &wl, const std::string& s)
{
WordPair* item = nullptr;
if (wl.first(item))
{
if (item->first == s)
{
++(item->second);
return;
}
while (wl.next(item))
{
if (item->first == s)
{
++(item->second);
return;
}
}
}
wl.insert(new WordPair { s, 1 });
}
void printList(WordList &wl)
{
WordPair *item = nullptr;
if (wl.first(item))
{
std::cout << item->first << " : " << item->second << "\n";
while (wl.next(item))
{
std::cout << item->first << " : " << item->second << "\n";
}
}
}
int main()
{
std::string words[10] = { "one", "two", "three", "four", "one",
"two", "three", "two", "three", "three" };
WordList wl;
for (int i = 0; i < 10; ++i)
{
incrementCount(wl, words[i]);
}
printList(wl);
}
Example: https://ideone.com/W4Slyq
Are you allowed to hold duplicates? If so you can just loop through the list.
int count(T &element) {
int numberOfDuplicates = 0;
for (int i = 0; i < numberOfElements; i++) {
if (data[i] == element) {
numberOfDuplicates++;
}
}
return numberOfDuplicates;
}

Exception thrown: read access violation. **_Right_data** was 0x4. C++

I tried everything and looked everywhere but I keep getting
Exception thrown: read access violation.
**_Right_data was 0x4.**
What is wrong with the code? I am not very good with C++ and don't like it at all but working on this school project and trying to figure out why I get the exception. Any help is appreciated
#include "Roster.h"
#include "Student.h"
#include "NetworkStudent.h"
#include "SecurityStudent.h"
#include "SoftwareStudent.h"
#include <iostream>
#include <string>
#include<vector>
#include<sstream>
#include<regex>
// Separates Data on basis of ,
template <class Container>
void splitString(const std::string& str, Container& cont)
{
char delim = ',';
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, delim)) {
cont.push_back(token);
}
}
// Checks and returns if email is valid or not
bool Email(std::string email)
{
const std::regex pattern("(\\w+)(\\.|_)?(\\w*)#(\\w+)(\\.(\\w+))+");
return regex_match(email, pattern);
}
// Main Function
int main()
{
Roster classRoster;
// Data Array
const std::string studentData[] = { "A1,John,Smith,John1989#gm ail.com,20,30,35,40,SECURITY",
"A2,Suzan,Erickson,Erickson_1990#gmailcom,19,50,30,40,NETWORK",
"A3,Jack,Napoli,The_lawyer99yahoo.com,19,20,40,33,SOFTWARE",
"A4,Erin,Black,Erin.black#comcast.net,22,50,58,40,SECURITY",
};
for (unsigned int i = 0;i < 5;i++)
{
std::vector<std::string> words;
std::string s = studentData[i];
// Splits Input
splitString(s, words);
// if Student belongs to Security
if (words.at(8) == "SECURITY")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new SecurityStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SECURITY);
}
// IF Student Belongs to Software
else if (words.at(8) == "SOFTWARE")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i]=new SoftwareStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, SOFTWARE);
}
// If Student Belongs to Network
else if (words.at(8) == "NETWORK")
{
int a[3] = { stoi(words.at(5)),stoi(words.at(6)),stoi(words.at(7)) };
classRoster.classRosterArray[i] = new NetworkStudent(words.at(0), words.at(1), words.at(2), words.at(3), stoi(words.at(4)), a, NETWORK);
}
}
std::cout << "\n---------Print All Student's Data------------\n";
classRoster.printAll();
std::cout << "\n---------------------------------------------\n";
std::cout << "Invalid Emails\n";
classRoster.printInvalidEmails();
std::cout << "\n--------------Days in Course------------------\n";
classRoster.printDaysInCourse("A2");
std::cout << "\n--------------By Degree Program------------------";
classRoster.printByDegreeProgram(3);
std::cout << "\n--------------Removes A3------------------\n";
classRoster.remove("A3");
classRoster.remove("A3");
return 0;
}
// Adds Student to Roster
void Roster::add(std::string studentID, std::string firstName, std::string lastName, std::string emailAddress, int age, int daysInCourse1, int daysInCourse2, int daysInCourse3, degree d)
{
if (d == SOFTWARE)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SoftwareStudent(studentID, firstName, lastName, emailAddress, age,a, d);
}
else if (d == NETWORK)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new NetworkStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
else if (d == SECURITY)
{
delete classRosterArray[4];
int a[3] = { daysInCourse1,daysInCourse2,daysInCourse3 };
classRosterArray[4] = new SecurityStudent(studentID, firstName, lastName, emailAddress, age, a, d);
}
}
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
// Prints All Data Of Array
void Roster::printAll()
{
for (unsigned i = 0;i < 5;i++)
{
std::cout << i + 1 << "\t";
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Prints Average Days in Course for a specific Student
void Roster::printDaysInCourse(std::string studentID)
{
int sum = 0;
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID)
{
int *p = classRosterArray[i]->getStudentDaysofCourses();
for (unsigned int j = 0;j < 3;j++)
sum += p[j];
delete[]p;
break;
}
}
std::cout << sum / 3.0;
}
// Prints Invalid Emails
void Roster::printInvalidEmails()
{
for (unsigned i = 0;i < 5;i++)
{
std::string email = classRosterArray[i]->getStudentEmail();
if (!Email(email))
{
std::cout << classRosterArray[i]->getStudentEmail();
//classRosterArray[i]->print();
std::cout << "\n";
}
}
}
// Prints By Degree Program
void Roster::printByDegreeProgram(int degreeProgram)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getDegreeProgram()==degreeProgram)
classRosterArray[i]->print();
std::cout << "\n";
}
}
// Destructor
Roster::~Roster()
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i]!=NULL)
delete classRosterArray[i];
}
}
Figured it out!
This part was causing the error
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0;i < 5;i++)
{
if (classRosterArray[i]->getStudentID() == studentID){
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID()<<"\n";
classRosterArray[i] = NULL;
}
}
std::cout << "Student ID Does not Exist \n";
}
Changed to
// Removes Student
void Roster::remove(std::string studentID)
{
for (unsigned i = 0; i < 5; i++)
{
if (classRosterArray[i] != NULL && classRosterArray[i]->getStudentID() == studentID) {
std::cout << "STUDENT REMOVED " << classRosterArray[i]->getStudentID() << "\n";
delete classRosterArray[i];
classRosterArray[i] = NULL;
return;
}
}
std::cout << "Student ID Does not Exist \n";
}

Printing from Trie

I have built a trie in C++ designed to hold words of sentences. Each sentence will have a weight which determines the order in which they should be output. I have several recursive functions that call other recursive functions, and the dilemma I am facing is that I want to print my list only once.
Basically my get function calls the printFromNode function which creates the vector of pairs p that I want to sort and print. If someone could point me in the right direction in how to do that it would be much appreciated.
Code:
Trie.cpp:
//#include "Trie.h"
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>
#include <stack>
using namespace std;
class Node
{
private:
string word = "";
bool endOfSentence = false;
int weight = -1;
public:
vector<Node> children = {};
Node() {
this->setWord("");
}
Node(string s){
this->setWord(s);
}
string getWord(){
return this->word;
}
void setWord(string s) {
this->word = s;
}
void setEOS(){
this->endOfSentence = true;
}
void setWeight(int weight){
this->weight = weight;
}
int getWeight() {
return this->weight;
}
};
class Trie
{
public:
Node root;
void add(vector<string> phrase, int weight, Node* n){
Node* current = n;
int w = weight;
int found = -1;
for (int i = 0; i < current->children.size(); i++) {
if (phrase[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1) {
current = &current->children[found];
phrase.erase(phrase.begin());
add(phrase, w, current);
}
else {
addPhrase(phrase, w, current);
}
}
void addPhrase(vector<string> phrase, int weight, Node* n) {
Node* current = n;
for (int i = 0; i < phrase.size(); i++) {
Node temp = *new Node(phrase[i]);
current->children.push_back(temp);
current = &current->children.back();
if (i == phrase.size() - 1) {
current->setEOS();
current->setWeight(weight);
}
}
}
void get(vector<string> search) {
Node* current = &this->root;
get(search, current);
}
void get(vector<string> search, Node* n) {
Node* current = n;
int found = -1;
//test search size
if (search.size() == 0) {
cout << "Please enter a valid search" << endl;
}
for (int i = 0; i < current->children.size(); i++) {
if (search[0] == current->children[i].getWord()) {
found = i;
}
}
if (found > -1 && search.size() == 1) {
current = &current->children[found];
printFromNode(*current);
maxNode(*current);
}
else if (found > -1 && search.size() != 1) {
current = &current->children[found];
search.erase(search.begin());
get(search, current);
}
else {
cout << "Not Found" << endl;
}
}
void printOutput(vector<pair<int,string>> p){
sort(p.begin(), p.end());
cout << p.size() << endl;
for (int i = 0; i < p.size(); i++) {
cout << p[i].second << " " << endl;
}
}
void printFromNode(Node n) {
vector<string> phrase = {};
vector <pair < int, string>> final = {};
printFromNode(n,phrase,final);
}
void printFromNode(Node n, vector<string> &v, vector<pair<int,string>> &p) {
string output;
if (n.getWord() == "") {
return;
}
for (int i = 0; i < n.children.size(); i++) {
if (n.children[i].getWeight() > 0) {
for (int i = 0; i < v.size(); i++)
{
output.append(v[i] + " ");
}
output.append(n.children[i].getWord());
p.push_back(make_pair(n.children[i].getWeight(), output));
}
v.push_back(n.children[i].getWord());
printFromNode(n.children[i], v, p);
v.pop_back();
sort(p.begin(), p.end());
}
return;
}
void maxNode(Node n) {
int max = 0;
int index = 0;
int temp = 0;
for (int i = 0; i < n.children.size(); i++) {
temp = n.children[i].children.size();
if (temp > max) {
max = temp;
index = i;
}
}
cout << n.children[index].getWord() << " " << max << endl;
}
};
Main.cpp:
#include "Trie.cpp"
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
// Initialize trie up here
Trie myTrie = *new Trie();
// parse input lines until I find newline
for(string line; getline(cin, line) && line.compare(""); ) {
stringstream ss(line);
string string_weight;
ss >> string_weight;
int weight = stoi(string_weight);
// I am just going to put these words into a vector
// you probably want to put them in your trie
vector<string> phrase = {};
for(string word; ss >> word;) {
phrase.push_back(word);
}
myTrie.add(phrase, weight, &myTrie.root);
vector<string> ans = {};
}
// parse query line
string query;
getline(cin, query);
stringstream ss(query);
vector<string> search = {};
for (string query; ss >> query;) {
search.push_back(query);
}
myTrie.get(search);
return 0;
}
You can remove recursive methods, and doing something like the following:
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <set>
class Node
{
public:
bool endOfSentence = false;
std::set<int> weights;
std::map<std::string, Node> children;
Node() = default;
const Node* get(const std::string& word) const
{
auto it = children.find(word);
if (it == children.end()) {
return nullptr;
}
return &it->second;
}
auto find_by_weight(int weight) const
{
return std::find_if(children.begin(),
children.end(),
[=](const auto& p){ return p.second.weights.count(weight);});
}
};
class Trie
{
Node root;
public:
void add(int weight, const std::vector<std::string>& phrase)
{
Node* node = &root;
for (const auto& word : phrase) {
node->weights.insert(weight);
node = &node->children[word];
}
node->weights.insert(weight);
node->endOfSentence = true;
}
bool contains(const std::vector<std::string>& phrase) const
{
const Node* node = &root;
for (const auto& word : phrase) {
node = node->get(word);
if (node == nullptr) {
return false;
}
}
return node->endOfSentence;
}
void print(int weight) const
{
const Node* node = &root;
const char* sep = "";
while (node) {
const auto it = node->find_by_weight(weight);
if (it == node->children.end()) {
break;
}
std::cout << sep << it->first;
sep = " ";
node = &it->second;
}
std::cout << std::endl;
}
void print_all() const
{
for (int i : root.weights) {
print(i);
}
}
};
And usage/Test:
int main(int argc, char* argv[]) {
const std::vector<std::vector<std::string>> sentences = {
{"My", "name", "is", "John"},
{"My", "house", "is", "small"},
{"Hello", "world"},
{"Hello", "world", "!"}
};
Trie trie;
int i = 0;
for (const auto& sentence : sentences) {
trie.add(i, sentence);
++i;
}
const std::vector<std::vector<std::string>> queries = {
{"My", "name", "is", "John"},
{"My", "house"},
{"Hello", "world"}
};
for (const auto& query : queries) {
std::cout << trie.contains(query) << std::endl;
}
trie.print_all();
}
Demo

Huffman Encoding priority queue

I'm working on an assignment where I should write an encoding and decoding application for the Huffman algorithm, based on a priority queue. We have to read a file, count the frequencies of the letters and then start the algorithm. I have the following problem:
My counting function works fine but it stores the frequency of every letter in an array - even if it's zero. But if I want to use that array to build my min heap I get major problems because of the zeros. Therefore I need to find a way to 'eliminate' them. I can't just skip them because then the min heap algorithm doesn't work anymore (wrong neighbours). So I wanted to transfer all non-zero entries in a vector and use the vector instead of the array. But there I always get an error that tells me that there's a problem with the vector size. I don't really know how to deal with that problem. (My min heap still uses the array because I can't even transfer the entries in a vector).
(Please ignore the main I was just trying stuff there!)
using namespace std;
struct huffman_node
{ char data;
int frequency;
bool vector;
huffman_node *left;
huffman_node *right;
};
void swap_huffman_nodes(huffman_node &a, huffman_node &b)
{ char store_data = a.data;
int store_frequency = a.frequency;
a.data = b.data;
a.frequency=b.frequency;
b.data = store_data;
b.frequency = store_frequency;
huffman_node *store_left = a.left;
huffman_node *store_right= a.right;
a.left = b.left;
a.right = b.right;
b.left = store_left;
b.right = store_right;
}
void print_node (huffman_node a)
{ cout << a.data << a.frequency << endl;
}
string line;
huffman_node Table[52];
vector <huffman_node> non_zero;
void build_table()
{ for (int i=1; i<27; i++)
{ Table[i].data = (char) (i+64);
Table[i].left = NULL;
Table[i].right = NULL;
}
for (int i=27; i<53; i++)
{ Table[i].data = (char) (i+70);
Table[i].left = NULL;
Table[i].right = NULL;
}
}
int counter =0;
void count(){
ifstream yourfile ("example.txt");
if (yourfile.is_open())
{
while ( getline (yourfile,line) )
{
/*cout << line << '\n'; */
unsigned long z=line.length();
int i=0;
while ( i < z)
{ /* cout << line[i] << endl; */
for (int j=65; j<91; j++)
{ if ((int) line[i] == j)
{ int k=-64+j;
Table[k].frequency++;
}
}
for (int j=97; j<123; j++)
{ if ((int) line[i] == j)
{ int k=-70+j;
Table[k].frequency++;
}
}
i++;
}
}
for (int i=1; i<53; i++)
{ if (Table[i].frequency!=0)
{ non_zero.push_back(Table[i]);
counter ++;
}
}
yourfile.close();
}
else cout << "Unable to open file";
}
class heap{
public:
void buildheap()
{
for (int i=1; i<53; i++)
{reheap(i);
};
}
void reheap(int new_index)
{ int parent_index = new_index/2;
while (parent_index > 0 && Table[parent_index].frequency > Table[new_index].frequency)
{ swap_huffman_nodes(Table[parent_index], Table[new_index]);
parent_index=parent_index/2;
new_index=new_index/2;
}
};
void delete_root()
{ int non_null_entries=0;
for (int i=1; i<53; i++)
{ if (Table[i].frequency!=-1) {non_null_entries++;};
}
swap_huffman_nodes(Table[1],Table[non_null_entries]);
Table[non_null_entries].frequency=-1;
non_null_entries--;
rebuild_heap_root_deletion(1, non_null_entries);
}
void rebuild_heap_root_deletion(int new_root,int non_null_entries){
int n;
if (2 * new_root > non_null_entries){
return;
}
if (2 * new_root + 1 <= non_null_entries
&& Table[2*new_root+1].frequency < Table[2*new_root].frequency){
n = 2 * new_root + 1;
} else {
n = 2 * new_root;
}
if (Table[new_root].frequency > Table[n].frequency){
swap_huffman_nodes(Table[new_root], Table[n]);
rebuild_heap_root_deletion(n, non_null_entries);
}
}
void add_element(huffman_node new_heap_element)
{ for (int i=52; i>0;i-- )
{ if (Table[i].frequency==-1 && Table[i-1].frequency!=-1)
{ Table[i]=new_heap_element;
reheap(i);
break;
}
}
}
void print_Table()
{
for (int i=1; i<53; i++)
{ /*if (Table[i].frequency != -1) */
cout << Table[i].frequency << " , " << Table[i].data << endl;
}
}
bool empty_heap() // a heap is empty here if there are only "invalid huffman nodes" in it except the first one that contains all information.
{ for (int i=2; i < 53; i++)
{ if (Table[i].frequency!=-1)
{ return false;}
}
return true;
}
};
int main(){
ofstream myfile ("example.txt");
if (myfile.is_open())
{
myfile << "Flori ist ein Koala.";
myfile << "";
myfile.close();
}
else cout << "Unable to open file";
build_table();
count();
heap allan;
cout << "\n";
allan.buildheap();
allan.print_Table();
int i=0;
/*while(i<500)
{
huffman_node base_1 = Table[1];
allan.delete_root();
huffman_node base_2 = Table[1];
allan.delete_root();
huffman_node parent;
parent.data = '/';
parent.frequency = base_1.frequency + base_2.frequency;
parent.left = &base_1;
parent.right = &base_2;
allan.add_element(parent);
i++;
}
return 0;
}