Huffman coding c++ - c++

So I am working on Huffman coding for a project. However, my code just doesn't work. When i ran it on visual studio, it didn't give me an error. What I was trying to do is to read a file and put all of them into a string. And get the frequency for each character in that string. But I think when the file got a little bit large, it seems like my code is running in a infinite loop. Can anyone explain anything to me? By the way, I had a sorted function that I used to sort a vector of node* by their frequency.
ifstream infile;
infile.open(filename);
string q;
string line;
while (getline(infile, line))
{
q += line;
}
char y;
int count = 0;
int check = 0;
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
}
}
if (check == 0)
{
for (int i = 0; i < q.size(); i++)
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}
sort(list1.begin(), list1.end(), sorter); //sort them from small to big
while (list1.size() > 1)
{
node*left = list1[0];
node*right = list1[1];
list1.erase(list1.begin(), list1.begin() + 2);
double sum = left->freq + right->freq;
node* x = new node;
x->freq = sum;
x->left = left;
x->right = right;
list1.push_back(x);
sort(list1.begin(), list1.end(), sorter);
}
list1.clear();
return true;
The following is my sort function
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() != '\0') {
return (int)a->getCharacter() < (int)b->getCharacter();
}
return false;
}
return a->getFrequency() < b->getFrequency();
}
} sorter;

I see two major problems.
You have a for loop inside a for loop both initializing and using int i
Change the variable name of the inner loop.
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
.
.
if (check == 0)
{
for (int i = 0; i < q.size(); i++) //Change this to int j for example
{
.
.
And the Sorter struct. I would rewrite it as this.
static struct {
bool operator()(NodeInterface* a, NodeInterface* b) {
if (a->getFrequency() == b->getFrequency()) {//if the frequencies are even,
if (b->getCharacter() == '\0') return false;
if (a->getCharacter() == '\0') return true;
return (int)a->getCharacter() < (int)b->getCharacter();
}
return a->getFrequency() < b->getFrequency();
}
} sorter;
A few suggestions for your for loop:
for (int i = 0; i < q.size(); i++) //if the string gets big, it seems to become an infinite loop in here
{
y = q[i];
//You can avoid this entire loop by using a structure like map
for (int x = i - 1; x > 0; x--) //make sure not counting the same char
{
if (y == q[x])
{
check++;
//break; //if you use a loop, break it once you find the character.
}
}
if (check == 0)
{
for (int j = 0; j < q.size(); j++)//Renamed variable + you can start this loop from j = i as you know there is no occurrence of y before that.
{
if (q[i] == y)
{
count++;
}
}
node*x = new node;
x->char1 = y; //my node have char
x->freq = count; //my node has frequency
list1.push_back(x);
}
count = 0;
check = 0;
}

Related

equal jump between numbers in two arrays

I want to compare two arrays. One of them is a subset of the other one. I want my function to return the minimum and equal gap between the numbers of the first subset array in the other array.
For example if I have
arr1 = 2,1,4,2,8,3
sub= 1,2,3
I want my function to return 1 because the mimimum gap between all this numbers are 1.
arr1 = 2,1,5,2,1,2,3
sub= 1,2,3
I want my function to return 0 because the mimimum gap between 1,2,3 in arr1 is 0
Here is the code I am trying to do: My code always return 0 can you help me understand why, and how can I solve this.
int gap(int* arr, int* sub, int sizeArr, int sizeSub)
{
int index = 0; int gap = 0; bool flag = true;
int i = -1;
for (int jump = 1; jump < sizeArr / sizeSub; jump++)
{
index = 0;
for (i = i +1; i < sizeArr; i++)
{
if (sub[index] == arr[i])
{
for (int j = i + jump, index = 1; j < sizeArr; j = j + jump, index++)
{
if (arr[j] != sub[index]) { flag = false; break; }
else if (arr[j] == sub[index] && index == sizeSub) { flag = true; break; }
}
}
if (!flag) { break; }
else { gap = jump; break; }
}
}
return gap;
}
You initially took gap equally 0 but i think more suit to not store gap
and start iterate jump from 0. And return jump immediately after you found that it is suit.
Also i think that store index in such manner as you it is bad idea, because you code return wrong answer on
int a[] = { 2,1,4,4,2,8,5,3 };
int s[] = { 1,2,3 };
I think you should declare variable as soon as possible, otherwise there will be undesirable side effects.
So you code can be rewritten as
int gap(int *arr, int *sub, int sizeArr, int sizeSub)
{
for (int jump = 0; 1 + (jump + 1) * (sizeSub - 1) <= sizeArr; jump++) {
for (int start_index = 0; start_index + (jump + 1) * (sizeSub - 1) < sizeArr; start_index++) {
bool flag = true;
for (int index = 0; index < sizeSub; ++index) {
if (arr[start_index + index * (jump + 1)] != sub[index]) {
flag = false;
break;
}
}
if (flag) {
return jump;
}
}
}
return -1; //or some value that indicate that there is no answer
}

My word search II solution is very slow (Leetcode 212)

My solution is correct and passes all test cases, but my solution is very slow (faster than 7% of C++ solutions).
Question:
Given an m x n board of characters and a list of strings words, return all words on the board.
Each word must be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once in a word.
For example:
Input: board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]
By the way, I don't have Leetcode premium and looked at the discussion. I see that other people are using recursion. I am using a stack, but this shouldn't really be a problem. Does anyone see any performance issues with my code? The complexity should be O(n^2*3^n)
class Solution {
public:
vector<string> findWords(vector<vector<char>>& board, vector<string>& words) {
vector<string> ret;
Trie* root = new Trie();
for (const auto &i:words) {
root->insert(i);
}
Trie* cnode = root;
int numRow = board.size();
int numCol = board[0].size();
vector<int> temp(numCol, 0);
vector<vector<int>> visited(numRow, temp);
for (int i = 0; i < numRow; ++i) {
for (int j = 0; j < numCol; ++j) {
stack<pair<int, int>> searcher;
searcher.push(make_pair(i,j));
while (!searcher.empty()) {
int row = searcher.top().first;
int col = searcher.top().second;
int cur = board[row][col] - 97;
if (visited[row][col]) {
cnode = cnode->parent;
visited[row][col] = 0;
searcher.pop();
} else if (cnode->child[cur] == nullptr) {
searcher.pop();
visited[row][col] = 0;
} else {
visited[row][col] = 1;
cnode = cnode->child[cur];
if (cnode->contain != "") {
ret.push_back(cnode->contain);
cnode->contain = "";
}
if (row + 1 < numRow && !visited[row + 1][col]) {
searcher.push(make_pair(row+1, col));
}
if (row - 1 >= 0 && !visited[row-1][col]) {
searcher.push(make_pair(row-1, col));
}
if (col + 1 < numCol && !visited[row][col+1]) {
searcher.push(make_pair(row, col+1));
}
if (col - 1 >= 0 && !visited[row][col-1]) {
searcher.push(make_pair(row, col-1));
}
}
}
}
}
return ret;
}
class Trie {
public:
vector<Trie*> child;
Trie* parent;
string contain;
Trie() {
child = vector<Trie*>(26, nullptr);
contain = "";
parent = nullptr;
}
void insert(string word) {
Trie* root = this;
for (int i = 0; i < word.size(); ++i) {
int loc = word[i] - 97;
if (root->child[loc] == nullptr) {
root->child[loc] = new Trie();
root->child[loc]->parent = root;
}
root = root->child[loc];
}
root->contain = word;
}
};
};

C++ Getting a "Control may reach end of a non-void function on a Johnson-Trotter code

What can I do to silence this warning? Do I need to add another return statement somewhere or do I need to change something within the functions?
Also could someone help me add arrows into the Johnson-Trotter algorithm. It would be nice to have them to show the direction but I am very confused on how to do it; though this isn't the main concern right now I just want the program to run. Thank you in advance.
These are the two functions with the warning:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
int printOnePerm(int k[], bool dir[], int n)
{
int mobile = getMobile(k, dir, n);
int pos = searchArr(k, n, mobile);
if (dir[k[pos - 1] - 1] == RIGHT_TO_LEFT)
{
swap(k[pos - 1], k[pos -2]);
}
else if (dir[k[pos - 1] - 1] == LEFT_TO_RIGHT)
{
swap(k[pos], k[pos -1]);
}
for(int i = 0; i < n; i++)
{
if (k[i] > mobile)
{
if (dir[k[i] - 1] == LEFT_TO_RIGHT)
{
dir[k[i] - 1] = RIGHT_TO_LEFT;
}
else if(dir[k[i] - 1] == RIGHT_TO_LEFT)
{
dir[k[i] - 1] = LEFT_TO_RIGHT;
}
}
}
for(int i = 0; i < n; i++)
{
cout << k[i];
}
cout << endl;
}
For the first function, searchArr(), one question is what do you expect it to return if the value is not found. Since the return values are in the range [1,n], I'm guessing that zero means not found.
I prefer to design functions which have a single return at the end, whenever possible. A default fail value can be set at the start of the function. I would exit the loop when the value is found, or fall through with the default value set.
Here is what I would write:
int searchArr(int k[], int n, int mobile)
{
int ret = 0; /* not found value */
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
ret = i + 1;
break;
}
}
return ret;
}
Alternately, and perhaps a bit more obscurely, if the value is not found in the array, then i will equal n when the for loop completes. This would be a possible function:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
break;
}
}
if (i < n)
return i + 1;
else
return 0;
}
The for loop can be shrunk to
for(int i = 0; i < n && k[i] != mobile; i++) ;
And the return can be shrunk to
return (i < n) ? i + 1 : 0;
Although I generally discourage using the ?: operator.
As mentioned above, the second function doesn't return any value and should be declared "void".
The first one:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
}
will not return anything if for some reason nothing in your array matches. In that case, you need to return a default or error value:
int searchArr(int k[], int n, int mobile)
{
for(int i = 0; i < n; i++)
{
if (k[i] == mobile)
{
return i + 1;
}
}
return -1; // not found
}
The second one doesn't seem to want to return anything. In C++, the way to do this is with a void, not an int (That was okay in C. C++ not so much):
// assuming we don't want to return anything
void printOnePerm(int k[], bool dir[], int n)

c++ inserting and sorting "empty" array at the same time

I am still learning C++, so please if this is a duplicate point me to correct topic as I couldn't find any good and useful explanation.
I try to create a function in my ascending_ordered_array class which will insert elements into "empty" array sorting them in the same time.
Below is my code so far, but unfortunately it doesn't work 100% correctly as it adds two largest numbers as a last for positions in array.
void ascOrderedArray::push(Datatype p_item, Datatype* p_array, int p_size)
{
int i, j = 0;
int temp, num;
if (p_array[j] < 0)
p_array[j] = p_item;
for (i = 0; i < (p_size - 1); i++)
{
num = p_size;
for (j = (p_size - 1); j >= i; j--)
{
if (p_array[num]> p_array[j])
num = j;
}
temp = p_array[num];
p_array[num] = p_item;
p_array[i] = temp;
}
}
Here is part of main which call function above trying place random numbers into it
for (i = 0; i < size; i++)
{
num = (i + 1)* (rand() % 100);
arr.push(num, arr, size);
}
any hints what I am missing out?
This is code I wrote and its work as long as it is no resize neccessary
void ascOrderedArray::push(Datatype p_item)
{
//check if array is big enough and resize it if necessary
if (m_numElements >= m_size)
resize();
//checking if array contains some elements and if not set its first to pased item
if (m_numElements == 0)
{
m_array[0] = p_item;
m_numElements++;
return;
}
else
{
int i = m_numElements;
while (i >= 0 && i <= m_numElements)
{
//shifting array elements
m_array[i] = m_array[i - 1];
if (p_item > m_array[i - 1])
{
m_array[i] = p_item;
break;
}
--i;
}
m_numElements++;
}
}

Checking for overlapping characters in a wordsearch game

I am developing a wordsearch generator to learn c++ better and I am stuck on preventing non-overlapping words from overlapping, such as a side-to-side word writing over a letter in a top-down word. Here is the code snippet:
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
What I have done was create a two dimensional array [10][11] filled with the 0 (zero) character so when I iterate through it all spaces are filled with 0 except for the 11th space in each line with a newline character to make a 10X10 grid. In my else if loop, the first part already has a word chosen and it tests if the word will fit in its proper space by checking if a 0 is present. If it runs into a non-zero character (such as if it runs into a letter from a top-down or diagonal word) the inner loop terminates, sets the boolean flag, and inputs a 1 (or any random letter) instead of the whole word. What happens is that the whole word is inserted anyways and overwrites one letter from the top down word. What am I doing wrong? Here is the rest of the code:
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
srand(time(NULL));
const char* const a_to_z = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
int random_char;
char wordsearch [10][11] = {0};
bool flag;
string words_array[] = {"CAT", "HELLO", "GOODBYE", "DOG", "BAT", "NEW", "SAY", "MAY", "DAY", "HAY"};
vector<string> words_vector (words_array, words_array + sizeof(words_array) / sizeof(string));
string words_found_array[] = {};
vector<string> words_found_vector (words_found_array, words_found_array + sizeof(words_found_array) / sizeof(string));
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
if (j == 10) {
wordsearch[i][j] = '\n';
}
else if (random_choice == 1 && random_word.size() <= 10-j && words_vector.size() != 0) {
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i][j+x] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
j += 1;
}
j -= 1;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else if (random_choice == 2 && random_word.size() <= 10-i && words_vector.size() != 0) {
int temp_i = i;
flag = true;
for (int x = 0; x < random_word.size(); x++) {
if (wordsearch[i+x][j] != '0') {
flag = false;
break;
}
}
if (flag = true) {
for (int x = 0; x < random_word.size(); x++) {
wordsearch[i][j] = random_word[x];
i += 1;
}
i = temp_i;
words_found_vector.insert(words_found_vector.begin(),words_vector[random_word_number]);
//words_vector.erase(words_vector.begin()+random_word_number);
}
else {
wordsearch[i][j] = '1';
}
}
else {
int random_char = rand() % 26 + 0;
wordsearch[i][j] = a_to_z[random_char];
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 11; j++) {
cout<<wordsearch[i][j];
}
}
cout<<"Your words are:"<<endl;
for (int x = 0; x < words_found_vector.size(); x++) {
cout<<words_found_vector[x]<<endl;
}
}
One more thing:
//words_vector.erase(words_vector.begin()+random_word_number);
crashes my program. I think it is a scoping issue with this:
int random_choice = rand() % 5;
int random_word_number = rand() % words_vector.size();
string random_word = words_vector[random_word_number];
What I want to do is eventually have the user give me a list of words they want to search for and this function chooses some of them and presents it to the user when playing the game. This not functioning correctly also causes duplicates to appear in the crossword and words-to-find-list.
Thank you for your help!
You have this error twice in your code:
if (flag = true)
That is not a condition, it's an assignment. It assigns true to flag, and the if-block will always execute. You need to make it a comparison condition by using ==
if (flag == true)
A more common way to write that in C++ would be just
if (flag)