#ifndef _LIBCPP_HASH
#define _LIBCPP_HASH
#include <iostream>
#include <string>
#include <string.h>
#include <iomanip>
#define PERTERB_SHIFT 5
using namespace std;
int FAIL = 0;
template <typename myType>
class HashMap
{
public:
HashMap()
{
Size = 8;
Resize = 2;
Keys = new int[8];
Values = new myType[8];
typesize = sizeof(myType);
Fill = 0;
memset(Keys, -1, 32);
memset(Values, 0, 8 * typesize);
}
~HashMap()
{
delete[] Keys;
delete[] Values;
}
HashMap(const HashMap &table)
{
Size = table.Size;
Keys = table.Keys;
Values = table.Values;
}
int GetSize() { return Size; }
// can't return get(key) because no binding of reference int to temporary int, so has the same body as get..
myType &operator[] (int hash)
{
register size_t perterb = hash;
register unsigned long j = 0;
register int temp = 0;
register int index = 0;
while ( Keys[index] != hash && Keys[index] != -1)
{
j = 5 * j + 1 + perterb;
perterb >>= PERTERB_SHIFT;
index = j % (2 << Resize);
//cout << "j : " << j << " temp: " << temp << " hash: " << hash << " index: " << index << endl;
}
if (Fill == (int)(Size * 2 / 3))
{
cout << "here" << endl;
Resize <<= 1;
int* tempkey = new int[Size*2];
myType* tempvalue = new myType[Size*2];
memset(tempkey, -1, Size*8);
memset(tempvalue, 0, Size*2*typesize);
copy(Keys, Keys + Size, tempkey);
copy(Values, Values + Size, tempvalue);
delete[] Values; delete[] Keys;
Keys = tempkey; Values = tempvalue;
Size <<= 1;
}
if (Keys[index] != hash) Fill ++;
Keys[index] = hash;
return Values[index];
}
bool insert(int key, myType value)
{
int index = key % Size;
short temp = 0;
while ((Keys[index] != key) && (Keys[index] != -1) && temp < Size)
{
index ++;
temp ++;
}
if (temp == Size)
{
int s = static_cast<int>(Size*4);
int* tempkey = new int[s];
myType* tempvalue = new myType[s];
for (int i = Size; i < s; i++)
{
tempkey[i] = -1;
tempvalue[i] = 0;
}
copy(Keys, Keys + Size, tempkey);
copy(Values, Values + Size, tempvalue);
delete[] Values; delete[] Keys;
Size *= 4;
Keys = tempkey;
Values = tempvalue;
}
Keys[index] = key;
Values[index] = value;
return true;
}
myType get(int key)
{
int index = key % Size;
short count = 0;
while (Keys[index] != key && count < Size)
{
index ++;
count ++;
}
if (count == Size)
{
try
{
throw key;
}
catch (int er)
{
cout << "KeyError: " << er << endl;
}
return FAIL;
}
return Values[index];
}
myType pop(int key)
{
int index = key % Size;
short count = 0;
while (Keys[index] != key && count < Size)
{
index ++;
count ++;
}
if ( count == Size )
{
try
{
throw key;
}
catch (int er)
{
cout << "KeyError: " << er << endl;
}
return FAIL;
}
myType temp = Values[index];
Values[index] = 0;
Keys[index] = -1;
return temp;
}
void Print()
{
cout << "index\t" << "key\t" << "value\t" << endl;
for (int i = 0; i < Size; i++)
{
cout << i << "\t" << Keys[i] << "\t" << Values[i] << "\t" << endl;
}
}
private:
int Size;
int Resize;
int* Keys;
myType* Values;
short typesize;
int Fill;
};
#endif
This is my code currently. The hash function is based off of Python dictionaries. The issue arises when trying to reference a hashmap entry after it has been inserted. If there was a collision during insertion, the [] operator will treat the reference as if it is trying to insert the value again and will stop at the first key = -1, instead of iterating until it finds the hash value in the key array. I'm able to address this issue with insert(), pop(), and get(), but I don't know how to deal with it for the [] operator, since it is used for both reference and assignments. It needs to know if it is followed by an assignment operator before it tries to either insert or get the hash.
I spent some time in the Python source code trying to figure out how they dealt with this issue but I couldn't figure it out.
I know this is a strange question, but I would really appreciate any help.