我正在尝试实现一个有效的哈希表,其中使用线性探测和步骤来解决冲突。此功能必须尽可能高效。没有不必要的=
或==
操作。我的代码工作正常,但效率不高。该效率由内部公司系统评估。它需要更好。
有两个类代表键/值对:CKey
和CValue
。这些类每个都有一个标准构造函数,复制构造函数和重写的运算符=
和==
。它们都包含一个getValue()
方法,返回内部私有变量的值。 getHashLPS()
中还有CKey
方法,它在哈希表中返回哈希位置。
int getHashLPS(int tableSize,int step, int collision) const
{
return ((value + (i*step)) % tableSize);
}
哈希表。
class CTable
{
struct CItem {
CKey key;
CValue value;
};
CItem **table;
int valueCounter;
}
方法
// return collisions count
int insert(const CKey& key, const CValue& val)
{
int position, collision = 0;
while(true)
{
position = key.getHashLPS(tableSize, step, collision); // get position
if(table[position] == NULL) // free space
{
table[position] = new CItem; // save item
table[position]->key = CKey(key);
table[position]->value = CValue(val);
valueCounter++;
break;
}
if(table[position]->key == key) // same keys => overwrite value
{
table[position]->value = val;
break;
}
collision++; // current positions is full, try another
if(collision >= tableSize) // full table
return -1;
}
return collision;
}
// return collisions count
int remove(const CKey& key)
{
int position, collision = 0;
while(true)
{
position = key.getHashLPS(tableSize, step, collision);
if(table[position] == NULL) // free position - key isn't in table or is unreachable bacause of wrong rehashing
return -1;
if(table[position]->key == key) // found
{
table[position] = NULL; // remove it
valueCounter--;
int newPosition, collisionRehash = 0;
for(int i = 0; i < tableSize; i++, collisionRehash = 0) // rehash table
{
if(table[i] != NULL) // if there is a item, rehash it
{
while(true)
{
newPosition = table[i]->key.getHashLPS(tableSize, step, collisionRehash++);
if(newPosition == i) // same position like before
break;
if(table[newPosition] == NULL) // new position and there is a free space
{
table[newPosition] = table[i]; // copy from old, insert to new
table[i] = NULL; // remove from old
break;
}
}
}
}
break;
}
collision++; // there is some item on newPosition, let's count another
if(collision >= valueCounter) // item isn't in table
return -1;
}
return collision;
}
当搜索到的-1
不在表格中或表格已满时,两个函数都会返回冲突计数(为了我自己的目的)并返回CKey
。
禁止使用墓碑。删除后重新进行是必须的。
答案 0 :(得分:2)
我看到的改进的最大变化是删除功能。您不应该重新整理整个表格。您只需要从删除点开始重新连接,直到到达空桶。此外,在重新散列时,请在执行重新散列之前删除并存储需要重新散列的所有项目,以便在重新散列时不会妨碍它们。
另一件事。使用所有哈希值,提高效率以减少loadFactor(元素与支持数组大小的比率)的最快方法。这减少了碰撞的数量,这意味着更少的迭代寻找开放点,并且更少的重新删除。在限制中,当loadFactor接近0时,碰撞概率接近0,并且它变得越来越像一个数组。虽然内存使用当然会增加。
的更新强> 的 您只需从删除点开始重新散列,然后按步长向前移动,直到达到空值。原因是这些是唯一可能因删除而改变其位置的对象。所有其他物体将最终到达完全相同的位置,因为它们不属于相同的“碰撞运行”。
答案 1 :(得分:0)
可能的改进是预先分配一个CItem数组,这将避免malloc()s / news和free()删除;你需要将数组更改为“CItem * table;”
但是又一次:你想要的基本上是一辆方形车轮的平稳骑行。