您的位置:首页 > 理论基础 > 数据结构算法

数据结构:散列2(探测法)

2017-01-10 17:53 246 查看
上一章的内容:散列1:分离链接法

对于List和Vector,都是使用自己实现的简单模板。Vector模板的实现 List模板的实现

散列表的填装因子(load factor)λ为散列表中的元素个数和散列表大小的比值。

探测散列表:在找到位置后,发现已经有数据,继续找下一个,直到找到位置。这种表叫做探测散列表。

再散列:当散列表中数据很多的时候,插入可能会失败,这个时候就扩展为原来大于2倍的新散列表,一般是找下一个素数。然后把旧表的数据放到新表中。

当表达式达到某一个填装因子时进行再散列。

再散列是一种非常耗时间的操作,但是因为不是经常发生,所以效果还好。

//使用探测法(probing hash tables)
template<typename HashedObj>
class HashTable2
{
public:
//构造函数
explicit HashTable2(int size = 101) :array(nextPrime(size))
{
makeEmpty();//设定结点的状态
}
//是否包含某个实体
bool contains(const HashedObj& x)const
{
return isActive(findPos(x));//找到位置,这个位置是否被使用的
}
//清空散列表
void makeEmpty()
{
currentSize = 0;
for (int i = 0; i < array.size(); i++)
{
array[i].info = EMPTY;
}
}
//插入数据
bool insert(const HashedObj& x)
{
int currentPos = findPos(x);//找到位置
if (isActive(currentPos))//已经有了就不插入了
{
return false;
}
//构建新的实体
array[currentPos] = HashEntry(x, ACTIVE);
++currentSize;
if (currentSize > array.size()/2)
{
rehash();//超过一半就重构
}
return true;
}
//删除实体
void remove(const HashedObj& x)
{
//找到位置
int currentPos = findPos(x);
if (!isActive(currentPos))
{
return false;//没有在使用的
}
array[currentPos].info = DELETED;//删除掉
return true;
}
enum EntryType{ ACTIVE, EMPTY, DELETED };
private:
struct HashEntry
{
HashedObj element;
EntryType info;
HashEntry(const HashedObj& e = HashedObj(), EntryType i = EMPTY)
:element(e), info(i){}
};
Vector<HashEntry> array;
int currentSize;
//当前位置的状态
bool isActive(int currentPos)const
{
return array[currentPos].info == ACTIVE;
}
//找实体的位置,理论上,是不会出现找到最后的位置也被使用掉的情况,因为超过一半了就要重构了
int findPos(const HashedObj& x)const
{
int offset = 1;
int currentPos = myhash(x);//散列函数
//如果位置为空或者找到了相等的,就中止
while (array[currentPos].info != EMPTY && array[currentPos].element != x)
{
currentPos += offset;
offset += 2;
if (currentPos >= array.size())
{
currentPos -= array.size();
}
}
return currentPos;
}
//重构一个散列表
void rehash()
{
Vector<HashEntry> oldArray = array;//原来的散列表
//扩展数组大小,原来的两倍之后的第一个素数
array.resize(nextPrime(2 * oldArray.size()));
for (int i = 0; i < array.size(); i++)
{
array[i].info = EMPTY;//将信息置为空
}
currentSize = 0;
//插入原来的数据
for (int i = 0; i < oldArray.size(); i++)
{
if (oldArray[i].info == ACTIVE)
{
insert(oldArray[i].element);
}
}
}
//散列函数
int myhash(const HashedObj& x)const
{
int hashVal = hash(x);
hashVal %= array.size();
if (hashVal < 0)
{
hashVal += array.size();
}
return hashVal;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息