#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
这是我目前的代码。哈希函数基于Python字典。插入哈希表条目后尝试引用该条目时会出现此问题。如果在插入过程中发生冲突,则[]运算符会将引用视为试图再次插入该值,并将在第一个键= -1处停止,而不是进行迭代直到在键数组中找到哈希值为止。我可以通过insert(),pop()和get()解决此问题,但是我不知道如何为[]运算符处理它,因为它既用于引用又用于赋值。在尝试插入或获取散列之前,它需要知道是否在赋值运算符之后。
我花了一些时间在Python源代码中试图弄清楚他们如何处理此问题,但我无法弄清楚。
我知道这是一个奇怪的问题,但我将非常感谢您的帮助。
答案 0 :(得分:1)
您的[]
可以返回代理类型,该代理类型又具有operator int()&&
用于读取和operator =(int const&)&&
用于写入。
存在一些问题,因为它与auto
的互动较差,但确实可以正常工作。
这是std向量bool为支持位压缩数据所做的工作。人们认为这是一个错误,但部分原因是不相关的。