《数据结构与算法分析C++描述》 分离链接(separate chaining)哈希表的C++实现
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
《数据结构与算法分析c++描述》 Mark Allen Weiss著
人民邮电大学出版
中文版第138-142面,分离链接(separate chaining)哈希表,侯捷将其翻译成开链
这应该是最容易实现的哈希表方法了,次容易的应该是线性搜索.
想起我到目前公司干的第二件事情,就是实现了一个文件系统,其核心模块就是一个类似MPQ的打包文件格式.而这个打包格式的核心模块就是一个线性哈希表的实现。只不过这次的实现不是在内存中,而是在文件上。这里顺面想说明是MPQ的实现是个很有意思的东西,感兴趣的可以去看看
http://shadowflare.samods.org/inside_mopaq/
inside mopaq是我见过最详细也最有用的资料,至于我刚开始工作的一些原始的资料记录就是非常凌乱了,但是希望有人在做同样工作的时候还能有一些参考价值吧。
http://blog.csdn.net/vagrxie/archive/2008/06/02/2504503.aspx
http://blog.csdn.net/vagrxie/archive/2008/06/02/2504515.aspx
并且,因为我以前已经实现了这么一个线性搜索的哈希表了,所以此次也不准备再实现一次了。
最后。。。。暴雪那个哈希算法的确是很不错,要求和一般的哈希算法不一样,一般的要求是哈希表总数为质数,其要求为2的幂。我在一次测试中发现,2万个文件的冲突次数大概在2千次,即1/10,远远低于书中低于1.5次的预期.
这一次是在VS中实现的,直接拷贝过来了,没有用vim了.
分离链接(separate chaining)哈希表的实现:
#ifndef
__SL_HASH_TABLE_H__
#define
__SL_HASH_TABLE_H__
#include
<algorithm></algorithm>
#include
<vector></vector>
#include
<list></list>
using
namespace
std;
// 两个Hash函数,第一个由书上的例子提供,散列效果不明
int
hash( const
string& key)
{
int
liHashVal = 0;
for( int
i = 0; i key.length(); ++i)
{
liHashVal = 37 * liHashVal + key[i];
}
return
liHashVal;
}
// 书中没有提供这个散列函数的实现。。。。。郁闷了,随便写一个了。。。。
int
hash( int
key)
{
return
key;
}
// 参考了>
static
const
int
gPrimesCount = 10;
static
unsigned
long
gPrimesArray[gPrimesCount] =
{
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593
};
inline
unsigned
long
NextPrime(unsigned
long
n)
{
const
unsigned
long* first = gPrimesArray;
const
unsigned
long* last = gPrimesArray + gPrimesCount;
const
unsigned
long* pos = lower_bound(first, last, n);
return
pos == last ? *(last - 1) : *pos;
}
template typename
HashedObj>
class
CSLHashTable
{
public:
// 书中无实现,无提示,我第一次编译才发现。。。。。
explicit
CSLHashTable(size_t
aiSize = 101) : miCurrentSize(aiSize)
{
moLists.resize(aiSize);
}
bool
Contains( const
HashedObj& x ) const
{
const
listHashedObj> & liListFinded = moLists[ MyHash(x)];
return
find( liListFinded.begin(), liListFinded.end(), x) != liListFinded.end();
}
void
MakeEmpty()
{
for( int
i=0; imoLists.size(); ++i)
{
moLists[i].clear();
}
}
bool
Insert( const
HashedObj& x)
{
listHashedObj> & liListFinded = moLists[ MyHash(x)];
if( find( liListFinded.begin(), liListFinded.end(), x) != liListFinded.end() )
{
return
false;
}
liListFinded.push_back(x);
if(++miCurrentSize > moLists.size())
{
ReHash();
}
return
true;
}
bool
Remove( const
HashedObj& x)
{
listHashedObj>& liListFinded = moLists[ MyHash(x)];
listHashedObj>::iterator
lit = find(liListFinded.begin(), liListFinded.end(), x);
if(lit == liListFinded.end())
{
return
false;
}
liListFinded.erase(lit);
--miCurrentSize;
return
true;
}
private:
vectorlistHashedObj> > moLists;
size_t
miCurrentSize;
void
ReHash()
{
vectorlistHashedObj> > loOldLists = moLists;
// 书中又一次的没有提供相关关键函数的实现,而且没有一点提示,NextPrime的含义自然是移到下一个素数上
moLists.resize( NextPrime( 2 * moLists.size()));
for( int
j=0; jmoLists.size(); ++j)
{
moLists[j].clear();
}
miCurrentSize = 0;
for(int
i=0; iloOldLists.size(); ++i)
{
listHashedObj>::iterator
lit = loOldLists[i].begin();
while(lit != loOldLists[i].end())
{
Insert(*lit++);
}
}
}
int
MyHash( const
HashedObj& x) const
{
int
liHashVal = hash(x);
liHashVal %= moLists.size();
if(liHashVal
{
liHashVal += moLists.size();
}
return
liHashVal;
}
};
#endif
// __SL_HASH_TABLE_H__
测试代码
#include
"SLHashTable.h"
#include
<iostream></iostream>
#include
<string></string>
using
namespace
std;
// 这里为了稍微纠正我最近用宏上瘾的问题。。。。强制自己使用了模板
// 其实还是有个问题。。。呵呵,具体的名字没有办法输出来了,当然,每次调用函数
// 输入字符串永远不在考虑的范围内
// 另外.....看到最后标准库的类型全名的时候,总是会感叹一下...实在是太长了,记得
// 有一次,一个复杂的带string的map,我根本没有办法从鼠标下面看到即时显示的调试信息
// 原因是类型太长了,加起来超出了一个屏幕!!!,所以实际的调试数值被挤到了屏幕以外!
// 所以只能通过添加watch的方式才能看到值-_-!!
template typename
HashedObj, typename
Table >
void
Test(HashedObj
x, Table& table)
{
if(table.Contains(x))
{
cout typeid(table).name() " Constains " x endl;
}
else
{
cout typeid(table).name() " don't Constains " x endl;
}
}
int
main()
{
// test Int
CSLHashTableint> loIntTable;
loIntTable.Insert(10);
loIntTable.Insert(20);
loIntTable.Insert(30);
loIntTable.Insert(40);
loIntTable.Insert(50);
Test(20, loIntTable);
Test(30, loIntTable);
Test(40, loIntTable);
Test(60, loIntTable);
Test(70, loIntTable);
CSLHashTablestring> loStrTable;
loStrTable.Insert(string("10"));
loStrTable.Insert(string("20"));
loStrTable.Insert(string("30"));
loStrTable.Insert(string("40"));
loStrTable.Insert(string("50"));
Test(string("20"), loStrTable);
Test(string("30"), loStrTable);
Test(string("40"), loStrTable);
Test(string("60"), loStrTable);
Test(string("70"), loStrTable);
return 0;
}
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie
分享到:
相关推荐
TestSeparateChaining.cpp: Test program for separate chaining hash tables (need to compile SeparateChaining.cpp also) QuadraticProbing.h: Header file for quadratic probing hash table QuadraticProbing...
单独的链哈希表一个集合,其元素为键值对,并通过单独的链接哈希表存储。 SeparateChainingHashTable共享Swift Dictionary的相同功能。
解决冲突的另一种方法称为开散列方法(opcnhashing,也称为链地址法,separate chaining),在这种方法中,首先按数据元素的关键字用某一个散列函数计算出数据元素的存放位置。通过散列函数计算出来的具有相同地址的...
搜索是计算机中重要且核心的任务。... 本文首先对单独的链接方法进行了额外的分析,并采用了升级方法,即与平衡二叉树(如BST和AVL)链接。 还提供了一些算法来帮助实现改进单独链接的性能并减少搜索元素时的搜索时间。
Introduction Hashing with chaining Cuckoo hashing
继MD5被攻破后,在Crypto2008上, Rivest提出了MD6算法,该算法的Block size为512 bytes(MD5的Block Size是512 bits), Chaining value长度为1024 bits, 算法增加了并行 机制,适合于多核CPU。 在安全性上,Rivest...
分离链(separate chaining) 253 5.7.2 hashtable 的桶子(buckets)与节点(nodes) 253 5.7.3 hashtable 的迭代器 254 5.7.4 hashtable 的数据结构 256 5.7.5 hashtable 的构造与内存管理 258 插入动作...
基本数据类型、算法和数据结构的介绍。 我们的重点是 Java 实现的应用程序和科学性能分析。 Part I focuses on elementary data structures, sorting, and searching. Topics include union-find, binary search, ...
SM4国密加密算法C语言实现 包括 Spec,C代码,测试用例和分组密码有五种工作体制:1.电码本模式(Electronic Codebook Book (ECB));2.密码分组链接模式(Cipher Block Chaining (CBC));3.计算器模式(Counter ...
分离链(separate chaining) 253 5.7.2 hashtable 的桶子(buckets)与节点(nodes) 253 5.7.3 hashtable 的迭代器 254 5.7.4 hashtable 的数据结构 256 5.7.5 hashtable 的构造与内存管理 258 插入动作...
Service Function Chaining (SFC) Architecture
MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476。 当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的...
链接 选择菜单 #Country State City 示例 #Ajax 获取 Country #Ajax 获取所选国家的州 #Ajax 获取所选州的城市 怎么跑 cd 链接 npm 安装 cd 链接 gulp
继MD5被攻破后,在Crypto2008上, Rivest提出了 MD6算法,该算法的Block size为512 bytes(MD5的Block Size是512 bits), Chaining value长度为1024 bits, 算法增加了并行 机制,适合于 多核CPU。 在安全性上,Rivest...
区块链是不同计算和经济学概念的组合,主要包括对等网络,不对称密码学,共识协议,分散存储,分散计算和智能合约以及激励机制。这些概念的综合将区块链定位为新技术并同时作为可编程平台和网络。...
正文 使用Antlr+Stringtemplate生成method chaining 在这里 http://blog.csdn.net/younggift/article/details/7028932
jQuery – 链(Chaining) 通过 jQuery,可以把动作/方法链接在一起。 Chaining 允许我们在一条语句中运行多个 jQuery 方法(在相同的元素上)。 jQuery 方法链接 直到现在,我们都是一次写一条 jQuery 语句(一条...
实现了链表法(Chaining)和开放地址寻址(Open Addressing)中的Hash表实现,开放地址寻址采用双重散列解决冲突
在寻找如何设计一个Javascript API的时候,发现了Method Chaining这个东西,方法链,看上去似乎很强大,也挺有意思的,而这个东西也是过去我们经常看到的。。 Javascript Method Chaining 在维基百科上有这样的解释:...