C++ Depth First Search of Trie with prefix parameter - c++

I'm trying to implement a trie that can print out the frequency of words with a given prefix.
Edit: Thanks to #kaidul-islam finding my error with the following error:
new_word->child[letter]->prefixes_++;
Below is the fixed code:
Trie Class:
class Trie
{
public:
Trie(): prefixes_(0), is_leaf_(false), frequency_(0)
{
for (int i=0; i<26; i++)
{
child[i] = nullptr;
}
}
virtual ~Trie();
//Child nodes of characters from a-z
Trie *child[26];
//vector<Trie> child;
int prefixes_;
//accessor & mutator functions
bool GetIsLeaf() { return is_leaf_; }
void SetIsLeaf(bool val) { is_leaf_ = val; }
int GetFrequency() { return frequency_; }
void SetFrequency(int val) { frequency_ = val; }
int GetPrefixes() { return prefixes_; }
void SetPrefixes(int val) { prefixes_ = val; }
bool is_leaf_;
private:
//bool is_leaf_;
int frequency_;
};
Function in Question:
void AddWord(string &word, Trie *root)
{
Trie *new_word = root;
new_word->prefixes_++;
for(unsigned int i = 0 ; i < word.length(); i++)
{
int letter = (int)word[i] - (int)'a'; //extract character of word
if(new_word->child[letter] == nullptr)
{
new_word->child[letter] = new Trie;
}
/*cout << "not value of x: " << new_word->child[letter]->GetPrefixes() << endl;
int x = (new_word->child[letter]->GetPrefixes())+1;
cout << "value of x: " << x << endl;
new_word->child[letter]->SetPrefixes(x);*/
new_word->child[letter]->prefixes_++;
new_word = new_word->child[letter];
}
new_word->SetFrequency(new_word->GetFrequency()+1);
/*
cout << "Word: " << word << endl;
cout << "frequency: " << new_word->GetFrequency() << endl;
cout << "prefixes: " << new_word->GetPrefixes() << endl;
cout << "is leaf: " << new_word->GetIsLeaf() << endl << endl;
*/
}

After a quick inspection, I found you didn't initialize member variables in your constructor.
Trie(): prefixes_(0),
is_leaf_(false),
frequency_(0) {
for(int i = 0; i < 26; i++) {
child[i] = nullptr;
}
}
Unlike global variable, there is no guarantee that prefixes_ will be 0 by default on declaration. And child[i] is not guaranteed to be nullptr too. You need to initialize everything.

Related

I m not getting correct output for pre and post order

// in this code I first created nodes stored them in a que and keep on removing them as I entered their left and right children. To make a node have no further children I entered -1 while entering data. Here I am not able to understand what is wrong with my code , I am getting wrong output for preorder and postorder traversals. It would be really great if you guys could help me out.
I made a class que for queue ds and inherited it in tree class in protected mode.
#include <iostream>
#include <math.h>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
class que
{
protected:
int start;
int end;
struct node **arr;
int n;
public:
que(int x)
{
n = x;
arr = new struct node *[n];
start = -1;
end = -1;
}
void isfull()
{
if (end == n)
cout << "Queue is full !!!" << endl;
return;
}
int isempty()
{
if (start == end)
{
start = -1;
end = -1;
cout << "Queue is empty !!!" << endl;
return 1;
}
return 0;
}
void enqu(struct node *x)
{
if (end == n)
{
cout << "called" << endl;
isfull();
return;
}
end++;
arr[end] = x;
}
struct node *dequ(void)
{
struct node *q = 0;
if (start == end)
{
isempty();
return q;
}
start++;
cout << "Element removed is ->" << arr[start] << endl;
return arr[start];
}
};
class tree : protected que
{
public:
struct node *head;
struct node *ptr;
tree(int n) : que(n)
{
head = 0;
ptr = 0;
enter();
}
void create(void)
{
ptr = new struct node;
ptr->left = 0;
ptr->right = 0;
}
void enter(void)
{
struct node *p;
if (head == 0)
{
create();
cout << "Enter root element of tree -> ";
cin >> ptr->data;
head = ptr;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
while (!isempty())
{
p = dequ();
cout << "Enter left child ->";
int x;
cin >> x;
if (x != -1)
{
create();
p->left = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
cout << "Enter right child ->";
cin >> x;
if (x != -1)
{
create();
p->right = ptr;
ptr->data = x;
cout << "Enquing ptr - " << ptr << endl;
enqu(ptr);
}
}
}
void inorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
cout << "--> " << yes->data << endl;
inorder(yes->right);
}
}
void preorder(struct node *yes)
{
if (yes != 0)
{
cout << "--> " << yes->data << endl;
inorder(yes->left);
inorder(yes->right);
}
}
void postorder(struct node *yes)
{
if (yes != 0)
{
inorder(yes->left);
inorder(yes->right);
cout << "--> " << yes->data << endl;
}
}
int count(struct node *yes)
{
static int x = 0, y = 0;
if (yes == 0)
return 0;
x = count(yes->left);
y = count(yes->right);
return x + y + 1;
}
int height(struct node *yes)
{
static int a = 0, b = 0;
if (yes == 0)
return 0;
a = count(yes->left);
b = count(yes->right);
if (a > b)
return a + 1;
else
return b + 1;
}
};
int main()
{
int x;
cout << "Enter height of tree - ";
cin >> x;
int max = 0;
max = pow(2, x + 1) - 1;
tree tr(max);
cout << "Preorder traversal -- " << endl;
tr.preorder(tr.head);
cout << "Inorder traversal -- " << endl;
tr.inorder(tr.head);
cout << "Postorder traversal -- " << endl;
tr.postorder(tr.head);
cout << "\n No. of elements -- " << tr.count(tr.head);
cout << "\n Height of tree --" << tr.height(tr.head);
}
The preorder and postorder functions doesn't call themselves recursively. Instead they call the inorder function, which will lead to all but the root will be printed using inorder.

Getting Misaligned access runtime error in c++ for a vector of pointers

Trie()
{
nxt.assign(26, NULL);
cout << nxt.size() << endl;
Trie* root = this;
isWord = false;
}
/** Inserts a word into the trie. */
void insert(string word)
{
auto node = root;
for (int i = 0; i < word.size(); i++)
{
cout << "node: " << node<< ":" << "word[i] -'a': " << word[i] - 'a' << endl;
if (node->nxt[word[i] - 'a'] == NULL ) // misaligned memory access here
node->nxt[word[i]-'a'] = new Trie();
node = node->nxt[word[i]-'a'];
}
node->isWord = true;
}
I am getting the following error although the vector seems to have correct length: Member access within misaligned address 0xbebebebebebebe for type 'Trie' which requires 8 byte alignment. Why is the nxt vector elements not accessible?
Update:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class Trie {
public:
Trie() {
nxt.assign(26, NULL);
isWord = false;
}
void insert(string word) {
auto node = this;
for(int i = 0; i < word.size(); i++) {
if (!node->nxt[word[i]-'a']) {
cout << " nxt entry not found... :" << word[i] << endl;
node->nxt[word[i]-'a'] = new Trie();
}
else {
cout << "nxt entry found! :" << word[i] << endl;
node = node->nxt[word[i]-'a'];
}
node->isWord = true;
}
}
bool search(string word) {
auto node = this;
for(int i = 0; i < word.size(); i++) {
if (!node->nxt[word[i]-'a']) return false;
node = node->nxt[word[i]-'a'];
}
return node->isWord ? true: false;
}
private:
vector<Trie*> nxt;
bool isWord;
};
int main() {
Trie* trie = new Trie();
trie->insert("test");
cout << "found test: " << trie->search("test") << endl;
cout << "success!" << endl;
return 0;
}
This runs! Bailey's comment helped me realize my mistake. I had declared a local root in ctor. The intent was to only initialize the class member, root! Thank you!

abnormal behaviour while displaying char array in C++ after object initialization

main():
char inp[] = "(A+B)/(C*D))";
Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
Here is Infix constructor:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
Infix is inheriting from a class 'Stack':
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
When I run the code in main, it displays unusual output:
Element In Stack: (
Operator Array: /*-+%
In main: +%
Stack Object Destroyed!
But, when in main, if the comment the line declaring 'Infix' object declaration, the code runs fine:
In main: (A+B)/(C*D))
EDITS:
Stack Class
#include<iostream>
using namespace std;
class Stack{
int top = -1;
char arr[100];
public:
bool push(char);
char pop();
char peek();
bool isEmpty();
void displayAll();
char returnTop() { return top;}
char* returnElement(int i) {
if(i > 98){
cout << "StackOutOfIndex";
return nullptr;
}
return &arr[i];
}
};
bool Stack:: push(char elementToPush) {
if(top > 98) {
cout << "\nStack Overflow!!";
return false;
} else {
arr[++top] = elementToPush;
return true;
}
}
char Stack:: pop() {
if(top <= -1) {
cout << "\nStack Underflow!!";
return ' ';
} else {
return (arr[top--]);
}
}
char Stack:: peek() {
if(top > 98) {
cout << "\nStack Overflow!!";
return ' ';
} else {
return arr[top];
}
}
bool Stack:: isEmpty() {
return (top <= 0);
}
void Stack:: displayAll() {
if(top <= -1) {
cout << "null";
return;
}
int i = top;
while (i >= 0) {
cout << arr[i] << " ";
--i;
}
cout << "\n";
}
Infix Class
#include<iostream>
#include<cstring>
#include<D:\Programs\11Stack.cpp>
using namespace std;
class Infix : public Stack {
string outputString;
char operatorArray[];
public:
Infix() {
push('(');
cout << "Element In Stack: " << *returnElement(returnTop()) << endl;
outputString = "";
strcpy(operatorArray, "/*-+%");
cout << "Operator Array: " << operatorArray << endl;
}
string infixToPostfix(char *, int);
bool manupulateOperator(char, int);
int checkPrecedence(char);
~Infix() {
cout << "\nStack Object Destroyed!" << endl;
}
};
string Infix:: infixToPostfix(char *str, int size) {
cout << "\nGiven String: " << str << endl;
int x;
for(int i = 0; i < size; ++size) {
x = str[i];
if(x != ' ') {
if(x == ')') {
while(returnTop() != '(') {
cout << pop() << " popped!\n";
}
cout << pop() << " popped!\n";
} else if(isalpha(x)) {
cout << x;
} /* else{ // scanned character is an operator
if(manupulateOperator(x, i)) {
} else {
return " ";
}
} */
}
}
return outputString;
}
bool Infix::manupulateOperator(char c, int position) {
try {
char topElement = *returnElement(returnTop());
if(checkPrecedence(c) == -1) {
cout << "\nErr\n";
}else if((checkPrecedence(c) > checkPrecedence(topElement)) || returnTop() == 0) {
push(c);
cout << c << " pushed!\n";
}
} catch(std::exception e) {
std::cerr << e.what() << '\n';
return false;
} catch (char* Ce) {
cout << Ce << endl;
}
return true;
}
int Infix::checkPrecedence(char c) {
/*
+ -> 1
- -> 1
* -> 2
/ -> 2
% -> 2
*/
switch(c) {
case '+':
return 1;
case '-':
return 1;
case '*':
return 2;
case '/':
return 2;
case '%':
return 2;
default:
// throw "Illegal Operator Detected!";
cout << "Illegal Operator Detected: " << c << endl;
return -1;
}
}
int main() {
cout << endl;
int x = 1;
char inp[] = "(A+B)/(C*D))";
//Infix i;
cout << "In main: " << inp /* + ')' */ << endl << endl;
// cout << i.infixToPostfix(input + ')', sizeof(input));
/* for(int i = 0; i < strlen(inp); ++i) {
cout << inp[i];
}
*/
return 0;
}
You are declaring operatorArray as an array of char but you are not assigning any memory for it! So, when you then call strcpy(operatorArray, "/*-+%"); in your Infix constructor, you are causing undefined behaviour by attempting to copy the given string constant to memory that hasn't been assigned - and this appears to be overwriting the inp[] array declared in your main.
To fix this, I would suggest giving your operatorArray member a specific size, which will be large enough to accommodate whatever string you want to copy to it - 8 characters will work in the sample code you've given:
class Infix : public Stack {
string outputString;
char operatorArray[8]; // Make this member a REAL array of characters.
//..
Your variable char operatorArray[] have no memory allocated when your constructor is called. When you use strcpy, you write to a place where you don't have permissions in your memory, and therefore on other informations.
To find these kinds of mistakes, I recommend using valgrind.
char operatorArray[]; is not allowed in Standard C++.
If you didn't see an error message then I would recommend adjusting compiler settings to follow the standard form of the language, this would have saved you a lot of time.

Circular Queue Bug Fix + Improvement Critiques

The issue is portrayed clearly in the display function.I wanted to display the array items in top, but I couldn't figure out a way to do so as it was constantly being incremented.
Instead of this...:
void CircularQueue :: Display() const {
for(int i = front; i < MAX; i++) {
cout << a[i] << endl;
}
}
**I want to display the circular queue using top:**
void CircularQueue :: Display() const {
for(int i = front; i < top; i++) {
cout << a[i] << endl;
}
}
In my main function, I enqueue'd 15 items, and as a result, top incremented 15 times. So obviously there would be 5 garbage values. How can I manipulate top so that the display function shows all 10 array values?
#include <iostream>
using namespace std;
#define MAX 10
class CircularQueue {
private:
int top;
int front;
public:
//assume that the max number of items in this circular queue is 10.
int a[MAX];
CircularQueue() {top = -1; front = -1;}
int enqueue(int x);
void dequeue();
void peekFront() const;
void peekBack() const;
void Display() const;
bool isEmpty();
};
//1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
//10,11,12,13,14,15,6,7,8,9
int CircularQueue :: enqueue(int x) {
//Problem: The array is actually growing in size.
++top;
a[top%10] = x;
int y = a[top%10];
cout << "Adding " << y << " to the queue." << endl;
if(top == 0) {
front = 0;
}
return y;
}
void CircularQueue :: dequeue() {
if(top < 0) {
cout << "The queue is empty." << endl;
} else {
int x = a[top];
cout << x << " will now be removed." << endl;
for(int i = 0; i <= top - 1; i++) {
a[i] = a[i+1];
}
top--;
x = a[top];
cout << "The last element of the queue is now: " << x << endl;
}
}
bool CircularQueue :: isEmpty() {
return top < 0;
}
void CircularQueue :: peekFront() const {
if(front < 0) {
cout << "The queue is empty." << endl;
} else {
int x = a[front];
cout << "The Front value is: " << x << endl;
}
}
void CircularQueue :: peekBack() const {
if(top < 0) {
cout << "The queue is empty." << endl;
} else {
int x;
x = a[top];
cout << "The back value is: " << a[top] << endl;
}
}
void CircularQueue :: Display() const {
for(int i = front; i < MAX; i++) {
cout << a[i] << endl;
}
}
int main() {
CircularQueue Aq;
Aq.enqueue(0);
Aq.enqueue(1);
Aq.enqueue(2);
Aq.enqueue(3);
Aq.enqueue(4);
Aq.enqueue(5);
Aq.enqueue(6);
Aq.enqueue(7);
Aq.enqueue(8);
Aq.enqueue(9); Aq.Display();
Aq.enqueue(10);
Aq.enqueue(11);
Aq.enqueue(12);
Aq.enqueue(13);
Aq.enqueue(14);
Aq.enqueue(15); Aq.Display();
return 0;
}
Expected output should be:
10,11,12,13,14,15,6,7,8,9
The array size should be 10 always. But when I keep enqueueing; The array size goes beyond 10.

hash table c++ strings

Trying to Implement a hash table in C++, Where the table has to take in string data and must hold at least 10 items. Implemented this below but doesn't compile and have broke it somehow :(, open to other ideas on how is best to implement or a fix for this one
Thanks
Someone be a legend please. :)
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class hash{
private:
static const int tableSize = 10;
struct item
{
string d;
item* next;
};
item* HashTable[tableSize];
public:
hash();//the constructor
int Hash(string key);
void AddItem(string d);//will add new item
int NumberOfItemsInBucket(int bucket);
void PrintTable();
void PrintItemsInBucket(int bucket);
};
hash::hash()
{
for(int i = 0;i < tableSize;i++)
{
HashTable[i] = new item;
HashTable[i]->d = "";
HashTable[i]->next = NULL;
}
};
void hash::AddItem(string d)
{
int bucket = Hash(d);
if(HashTable[bucket]->d == "")
{
HashTable[bucket]->d = d;
}
else
{
item* Ptr = HashTable[bucket];
item* n = new item;
n->d = d;
n->next = NULL;
while(Ptr->next != NULL)
{
Ptr = Ptr->next;
}
Ptr->next;
}
}
int hash::NumberOfItemsInBucket(int bucket)
{
int slot = 0;
if(HashTable[bucket]->d == "")
{
return slot;
}
else
{
slot++;
item* Ptr = HashTable[bucket];
while(Ptr->next != NULL)
{
slot++;
Ptr = Ptr->next;
}
}
return slot;
}
void hash::PrintTable()
{
int number;
for(int i = 0;i < tableSize;i++)
{
number = NumberOfItemsInBucket(i);
cout << "--------------------\n";
cout << "bucket = " << i << endl;
cout << "Data: " << HashTable[i]->d << endl;
cout << "No. of items = " << number << endl;
cout << "--------------------\n";
}
}
void hash::PrintItemsInBucket(int bucket){
item* Ptr = HashTable[bucket];
if(Ptr->d == ""){
cout << "bucket " << bucket << " is empty!\n";
}else{
cout << "Bucket " << bucket << " contains this: " << endl;
while(Ptr != NULL){
cout << "--------------------\n";
cout << Ptr->d << endl;
cout << "--------------------\n";
Ptr = Ptr->next;
}
}
}
int hash::Hash(string key){
int hash = 0;
int index;
for(int i = 0;i < key.length();i++)
{
hash = hash + (int)key[i];
//cout << "Hash = " << hash << endl; //displays the hash function result
}
index = hash % tableSize;
return index;
}
int main (){
hash newHash;
newHash.AddItem("restaurant");
newHash.AddItem("innovation");
newHash.AddItem("vegetarian");
newHash.AddItem("opposition");
newHash.AddItem("attractive");
newHash.AddItem("incredible");
newHash.AddItem("assessment");
newHash.AddItem("illustrate");
newHash.AddItem("presidency");
newHash.AddItem("background");
newHash.PrintTable();
//newHash.PrintItemsInBucket();
return 0;
}
Compile errors:
note: class hash
error: 'newHash' not declared in the scope
error: reference to 'hash' is ambiguous
Just remove the using manespace std; and add explicitly add std:: to endl, cout, and string.