哈希表,12个字符串使用BKDR算法生成的整数再用取余法居然冲突6次!!!!

xwhmm 2013-06-22 12:55:25
最近在看hash表,发现网上的BKDR算法都说处理字符串很好,我就试了试,结果发现用取余法,竟然冲突了6次,到底怎么回事,我看到人家帖子里面测试都是100万个字符串才冲突了4000多次,难道是我用的不对吗?贴上代码,高手求教

int CTreeEventDlg::ModMethod(int iKeyNum)
{//取余
int iHashKey=iKeyNum%11;
return iHashKey;
}

int CTreeEventDlg::OpenAddressing(int iHashKeyFailed,int iDi)
{//二次探测法
int iHashKey=0;
iHashKey=(iHashKeyFailed+iDi)%12;
return iHashKey;
}

// BKDR Hash
unsigned int BKDRHash(char *str)
{//网上找的BKDR
unsigned int seed = 131; // 31 131 1313 13131 131313 etc..
unsigned int hash = 0;

while (*str)
{
hash = hash * seed + (*str++);
}

return (hash & 0x7FFFFFFF);
}
void CTreeEventDlg::OnButton11()
{
// TODO: Add your control notification handler code here
StaffInfo staffs[12];
staffs[0].phoneNum="www.2013666.com ";
staffs[1].phoneNum="13927156666";
staffs[2].phoneNum="@_fdsa";
staffs[3].phoneNum="gfdgfdsgfdsg";
staffs[4].phoneNum="*___ ";
staffs[5].phoneNum="ewqe23e";
staffs[6].phoneNum="543254328800";
staffs[7].phoneNum="0!!!!!!!!!!";
staffs[8].phoneNum="13725036666";
staffs[9].phoneNum="8800676547654765";
staffs[10].phoneNum="613425386666";
staffs[11].phoneNum=" Hello";

StaffInfo staffsHash[12];
int iCount=sizeof(staffs)/sizeof(*staffs);
for (int iCountLoop=0;iCountLoop<iCount;iCountLoop++)
{
staffsHash[iCountLoop].phoneNum=NULL;
}
for (iCountLoop=0;iCountLoop<iCount;iCountLoop++)
{
unsigned int iBKDRValue=BKDRHash(staffs[iCountLoop].phoneNum);
int iHashIndex=ModMethod(iBKDRValue);
int iPositive=0;
int iLoopNum=0;
while(staffsHash[iHashIndex].phoneNum!=NULL || iHashIndex<0)
{
//进入此处循环表示哈希表的时候遇到了冲突
if (iPositive==0)
{
int iDi=iLoopNum*iLoopNum;
iHashIndex=OpenAddressing(iHashIndex,iDi);
iPositive=-1;
}else if (iPositive==-1)
{
int iDi=-iLoopNum*iLoopNum;
iHashIndex=OpenAddressing(iHashIndex,iDi);
iPositive=0;
}
iLoopNum++;
}
if (staffsHash[iHashIndex].phoneNum==NULL)
{
staffsHash[iHashIndex].phoneNum=staffs[iCountLoop].phoneNum;
}
}
int a=1;
}


谁知道的能帮忙解释一下吗?
...全文
247 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
xwhmm 2013-06-26
  • 打赏
  • 举报
回复
引用 4 楼 u010936098 的回复:
hash函数的算法是否合适,取决于你的数据。 hash函数的结果都是要取余数。 你的table与数据量完全相等,无论采用哪种开放定址法都会加剧冲突的发生,建议将table长度增加至少一半,或改用拉链法解决冲突。
虽然增加了表长变成了24,但是还是6次冲突,无解,先给分吧,还是谢谢你啊
xwhmm 2013-06-24
  • 打赏
  • 举报
回复
引用 4 楼 u010936098 的回复:
hash函数的算法是否合适,取决于你的数据。 hash函数的结果都是要取余数。 你的table与数据量完全相等,无论采用哪种开放定址法都会加剧冲突的发生,建议将table长度增加至少一半,或改用拉链法解决冲突。
哦,我倒是疏忽了表长的问题..............
橡木疙瘩 2013-06-22
  • 打赏
  • 举报
回复
hash函数的算法是否合适,取决于你的数据。 hash函数的结果都是要取余数。 你的table与数据量完全相等,无论采用哪种开放定址法都会加剧冲突的发生,建议将table长度增加至少一半,或改用拉链法解决冲突。
xwhmm 2013-06-22
  • 打赏
  • 举报
回复
引用 2 楼 u010936098 的回复:
hashmap是很好用,便使用它的人首先要做好心理准备:世界上并不存在一个通用并且优秀的hash算法,必须针对你所面对的问题域进行选择。当你选择好一个hash算法之后,要用大量的、接近真实的数据进行测试并调整。 如果你说“我的hashmap要支持任何字符串搜索需求,所有的合法的可以用std::string存储的字符串,所有char类型都可以存储并且出现机率相同”,那么取前4个字符组合成整数就是最好的hash——不过它在面对任何一个具体领域时都不会表现足够好。 凡是不想花时间设计hash函数的,请忘记unordered_map,map就是你最好的选择。
我的代码有问题吗?用的这个算法用对了吗? 我的步骤对吗?还有BKDR算法一般是怎么使用的呢?也是用来取余吗?如果是取余,我的取余有问题吗?
橡木疙瘩 2013-06-22
  • 打赏
  • 举报
回复
hashmap是很好用,便使用它的人首先要做好心理准备:世界上并不存在一个通用并且优秀的hash算法,必须针对你所面对的问题域进行选择。当你选择好一个hash算法之后,要用大量的、接近真实的数据进行测试并调整。 如果你说“我的hashmap要支持任何字符串搜索需求,所有的合法的可以用std::string存储的字符串,所有char类型都可以存储并且出现机率相同”,那么取前4个字符组合成整数就是最好的hash——不过它在面对任何一个具体领域时都不会表现足够好。 凡是不想花时间设计hash函数的,请忘记unordered_map,map就是你最好的选择。
橡木疙瘩 2013-06-22
  • 打赏
  • 举报
回复
我一般用37 12个字符串数据量太小,不足以作出判断。 此外,这种算法主要是用于hash大量的英文单词,面对楼主提供的这一类怪异文本不一定好用。 如果找不到好的hash函数,那就干脆不用hashmap,改用二叉树、key树等搜索结构。

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧