WitchKing17 WitchKing17 - 15 days ago 5
C++ Question

Counting number of occurrences of a string in a Hash Table

I am writing my own HashTable class in C++ and need to output to the user the number of occurrences of each string in the table. For example, if this is the input:

testing, 1, 2, testing
, and this is the hash table (done with chaining, and node pointers):

[0]->testing, testing
[1]->2
[2]->1


this would be the output to the user (the count, followed by the word):

2 testing
1 2
1 1


The problem I'm having is how to keep track of how many of each word is in the Hash Table, or how to find it. I started with this question but was unable to implement another array in my code.

I also tried the solution in this question, but it didn't work because of my use of pointers/chained hashing.

My question is, do I need to use a separate array of strings to keep track of what's already been used, or is there an easy way to recursively go through each index of the Hash Table and print out the number of occurrences of each string? I think I need to accomplish this in either my
insert
function or my
printData
function.

For reference, here is my code:

HashTable.h
:

#include <string>
#include <iostream>

using namespace std;

struct Entry {
string word;
Entry* next;
};

class HashTable {
public:
HashTable();
HashTable(int);
int hash(string);
void insert(string);
void printData();
int getCapacity() const;
private:
//Member variables
int CAPACITY; // The initial capacity of the HashTable
Entry **data; // The array to store the data of strings (Entries)
};


HashTable.cpp
:

#include "HashTable.h"

HashTable::HashTable()
{
CAPACITY = 0;
data = new Entry*[0];
}

HashTable::HashTable(int _cap)
{
CAPACITY = _cap;
data = new Entry*[_cap];

for (int i = 0; i < CAPACITY; i++) {
data[i] = new Entry;
data[i]->word = "empty";
data[i]->next = nullptr;
}
}

int HashTable::hash(string key)
{
int hash = 0;

for (unsigned int i = 0; i < key.length(); i++) {
hash = hash + (int)key[i];
}

return hash % CAPACITY;
}

void HashTable::insert(string entry)
{
int index = hash(entry);

if (data[index]->word == "empty") {
data[index]->word = entry;
} else {
Entry* temp = data[index];
Entry* e = new Entry;
e->word = entry;
e->next = nullptr;

while (temp->next != nullptr) {
temp = temp->next;
}

temp->next = e;
}
}

void HashTable::printData()
{
for (int i = 0; i < CAPACITY; i++) {
if (data[i]->next != nullptr) {
while(data[i]->next != nullptr) {
cout << data[i]->word << " -> ";
data[i] = data[i]->next;
}

cout << data[i]->word << endl;
} else {
cout << data[i]->word << endl;
}
}
}

int HashTable::getCapacity() const
{
return CAPACITY;
}


NOTE: I can't use any function/data structure from the standard C++ Library.

Answer

I only see two options here

  1. Traverse entire linked list to count occurances. Use a map< string, int > to count occurances for each string.

  2. You should make your linked list sorted. So when you insert a new node, you will insert it in its exact place. You can use strcmp for comparison. This way you can count every word exactly in one traverse and using just one integer variable, but your insert time and complexity will increase.

Comments