`
webcenterol
  • 浏览: 911288 次
文章分类
社区版块
存档分类
最新评论

《数据结构与算法分析C++描述》 分离链接(separate chaining)哈希表的C++实现

 
阅读更多

《数据结构与算法分析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

分享到:
评论

相关推荐

    c++数据结构与算法实现

    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字典相同的公共接口

    单独的链哈希表一个集合,其元素为键值对,并通过单独的链接哈希表存储。 SeparateChainingHashTable共享Swift Dictionary的相同功能。

    数据结构实验:链地址法解决冲突构建散列表

    解决冲突的另一种方法称为开散列方法(opcnhashing,也称为链地址法,separate chaining),在这种方法中,首先按数据元素的关键字用某一个散列函数计算出数据元素的存放位置。通过散列函数计算出来的具有相同地址的...

    BST和AVL ISSN链接方法改进的算法分析-研究论文

    搜索是计算机中重要且核心的任务。... 本文首先对单独的链接方法进行了额外的分析,并采用了升级方法,即与平衡二叉树(如BST和AVL)链接。 还提供了一些算法来帮助实现改进单独链接的性能并减少搜索元素时的搜索时间。

    算法与数据结构设计课件-Cuckoo

    Introduction Hashing with chaining Cuckoo hashing

    MD6源码算法资源下载 asp C++最新安全加密算法

    继MD5被攻破后,在Crypto2008上, Rivest提出了MD6算法,该算法的Block size为512 bytes(MD5的Block Size是512 bits), Chaining value长度为1024 bits, 算法增加了并行 机制,适合于多核CPU。 在安全性上,Rivest...

    STL 源码剖析(侯捷先生译著)

    分离链(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职业笔试题-Algorithms:算法

    基本数据类型、算法和数据结构的介绍。 我们的重点是 Java 实现的应用程序和科学性能分析。 Part I focuses on elementary data structures, sorting, and searching. Topics include union-find, binary search, ...

    SM4国密加密算法C语言实现

    SM4国密加密算法C语言实现 包括 Spec,C代码,测试用例和分组密码有五种工作体制:1.电码本模式(Electronic Codebook Book (ECB));2.密码分组链接模式(Cipher Block Chaining (CBC));3.计算器模式(Counter ...

    STL源码剖析.pdg

    分离链(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

    Service Function Chaining (SFC) Architecture

    MD5加密算法(Java语言描述)

     MD5中有四个32位被称作链接变量(Chaining Variable)的整数参数,他们分别为:A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476。  当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的...

    chaining:javascript jquery 链接车把表达

    链接 选择菜单 #Country State City 示例 #Ajax 获取 Country #Ajax 获取所选国家的州 #Ajax 获取所选州的城市 怎么跑 cd 链接 npm 安装 cd 链接 gulp

    md6算法c语言实现

    继MD5被攻破后,在Crypto2008上, Rivest提出了 MD6算法,该算法的Block size为512 bytes(MD5的Block Size是512 bits), Chaining value长度为1024 bits, 算法增加了并行 机制,适合于 多核CPU。 在安全性上,Rivest...

    Off-chaining Models and Approaches to Off-chain Computations

    区块链是不同计算和经济学概念的组合,主要包括对等网络,不对称密码学,共识协议,分散存储,分散计算和智能合约以及激励机制。这些概念的综合将区块链定位为新技术并同时作为可编程平台和网络。...

    使用Antlr+Stringtemplate生成method chaining

    正文 使用Antlr+Stringtemplate生成method chaining 在这里 http://blog.csdn.net/younggift/article/details/7028932

    jQuery – 链(Chaining)

    jQuery – 链(Chaining) 通过 jQuery,可以把动作/方法链接在一起。 Chaining 允许我们在一条语句中运行多个 jQuery 方法(在相同的元素上)。 jQuery 方法链接 直到现在,我们都是一次写一条 jQuery 语句(一条...

    HashTable的java实现

    实现了链表法(Chaining)和开放地址寻址(Open Addressing)中的Hash表实现,开放地址寻址采用双重散列解决冲突

    Javascript中的方法链(Method Chaining)介绍

    在寻找如何设计一个Javascript API的时候,发现了Method Chaining这个东西,方法链,看上去似乎很强大,也挺有意思的,而这个东西也是过去我们经常看到的。。 Javascript Method Chaining 在维基百科上有这样的解释:...

Global site tag (gtag.js) - Google Analytics