【习作】用二叉树处理溢出的哈希表
问题综述
这是我在学习数据结构时遇到的一个习题,要求使用二叉树处理存数冲突,而不是线性探查表使用的顺序向下存的方法。觉得有点意思,所以放上来。很显然,使用二叉树不会出现溢出的方法,而且也能享受二叉树的优秀搜索、插入、删除性能。
借物表
- 二叉树使用std::set
- hash函数采用std::hash
- 代码参考Sartaj Sahni的《数据结构、算法与应用》
基本思路
维护一个一维数组,类型为set*,用作hash table。如果出现冲突,用set处理。
代码
#include<iostream>
#include<string>
#include<set>
usingnamespace std;
classHashTable_BTree
{
//用二叉树实现溢出处理的哈希表
set<pair<string,int>>** table;//表头
hash<string> hash;//使用stl自带的hash
int dSize;
int divisor;//除数,决定树的数量
public:
HashTable_BTree(int theDivisor)
{
divisor = theDivisor;
dSize =0;
table =newset<pair<string,int>>*[divisor];
for(int i =0; i < divisor; i++)
{
table[i]=newset<pair<string,int>>;
table[i]->insert(pair<string,int>("ROOT",0));//将根节点占用了,原因是为了实现search方法
}//初始化每个树
}
set<pair<string,int>>::iterator search(string key);
const pair<string,int>* find(string key);
void insert(pair<string,int>& ele);
};
set<pair<string,int>>::iterator HashTable_BTree::search(string key)
{
int b = hash(key)%divisor;//知道应该放进第几个桶
set<pair<string,int>>::iterator it = table[b]->begin();//获得树的迭代器
while(it!=table[b]->end())
{
if(it->first == key)
{
return it;//发现节点,返回指向该节点的迭代器
}
it++;
}
return it;//没有找到,返回指向根节点的迭代器
}
const pair<string,int>*HashTable_BTree::find(string key)
{
set<pair<string,int>>::iterator it= search(key);
//这时,由search()方法可以看出,如果it指向根,说明没找到
//如果it指向非根,说明找到了
int b = hash(key)% divisor;
if(it->first ==string("ROOT"))returnnullptr;
const pair<string,int>* answear =&it.operator*();//这里有点混淆,可以指出迭代器的操作符*是重载的,不是通常的取值操作,所以&*it是有效的,为了方便辨认,我写成左式这样
return answear;
}
voidHashTable_BTree::insert(pair<string,int>& ele)
{
//插入操作
int b = hash(ele.first)% divisor;
table[b]->insert(ele);
}
int main()
{//测试程序
HashTable_BTree a(10);
a.insert(pair<string,int>("Hello",64));
if(a.find(string("Hello"))!=nullptr)
cout <<"found one!"<< endl;
system("pause");
}
改进
很显然,search方法用的是遍历,没有充分享受set的优秀性能,但是因为set存的是指针pair*,需要自己写一个大小比较获得最优性能