HashTable和HashMap
2015-12-20 22:19
176 查看
在平常的应用中,经常遇到一些需要查询某个元素的情况,一般来说就有3种不同复杂度的做法:
把元素简单放进线性表中,这样每次查询需要遍历一遍线性表,复杂度是O(n)的
把元素放进平衡树中,这样每次查询复杂度是O(logn)的
把元素放进hash表中,这样查询的均摊复杂度变为O(1)
实际应用中一般不采用1,而采用2和3。平衡树的优点是查询稳定,缺点是查询次数多时较慢;hash表的优点是查询的平均时间短,缺点是某几次查询可能比较慢。具体根据实际情况来选择。
3种方法的原理比较:
一般线性表,所有元素分布在一条链上,通过遍历这条链来查询元素
平衡树,二分搜索的基本思想以及维护平衡性质来限制深度保证O(logn)的复杂度
hash表,改进普通线性表的存储方式,使用某种分配机制使得元素尽量分布于不同的链上,从而只需遍历元素所在链即可。
HashTable的实现:
利用邻接表,然后设计一个散列函数,就可以得到HashTable的一个实现。散列函数的好坏决定了hash表的好坏。我这里选择对质数取模作为散列函数(选择非质数确实效率要下降不少)。
HashMap的实现:
有了HashTable,HashMap就不难了。HashMap相当于键的HashTable,再另外加上值的一个线性表,然后让地址对应起来即可,即可以由键来得到存对应值的地址。
实现得比较粗糙,将就着用吧~
把元素简单放进线性表中,这样每次查询需要遍历一遍线性表,复杂度是O(n)的
把元素放进平衡树中,这样每次查询复杂度是O(logn)的
把元素放进hash表中,这样查询的均摊复杂度变为O(1)
实际应用中一般不采用1,而采用2和3。平衡树的优点是查询稳定,缺点是查询次数多时较慢;hash表的优点是查询的平均时间短,缺点是某几次查询可能比较慢。具体根据实际情况来选择。
3种方法的原理比较:
一般线性表,所有元素分布在一条链上,通过遍历这条链来查询元素
平衡树,二分搜索的基本思想以及维护平衡性质来限制深度保证O(logn)的复杂度
hash表,改进普通线性表的存储方式,使用某种分配机制使得元素尽量分布于不同的链上,从而只需遍历元素所在链即可。
HashTable的实现:
利用邻接表,然后设计一个散列函数,就可以得到HashTable的一个实现。散列函数的好坏决定了hash表的好坏。我这里选择对质数取模作为散列函数(选择非质数确实效率要下降不少)。
HashMap的实现:
有了HashTable,HashMap就不难了。HashMap相当于键的HashTable,再另外加上值的一个线性表,然后让地址对应起来即可,即可以由键来得到存对应值的地址。
实现得比较粗糙,将就着用吧~
template<typename T, int N, int SZ> struct HashTable { T table[SZ]; int nxt[SZ]; int last ; int total; HashTable(){ clear(); } void clear() { mset(last, -1); total = 0; } int add(T x) { int pos = getMod(x); table[total] = x; nxt[total] = last[pos]; last[pos] = total ++; return total - 1; } int find(T x) { int pos = getMod(x), i = last[pos]; for (; ~i; i = nxt[i]) { if (table[i] == x) break; } return i; } int getMod(string x) { int n = x.length(), mm = 0; up(i, n) { mm = (mm * 128 + x[i]) % N; } return mm; } inline int getMod(ll x) { return x % N; } }; template<typename T, typename T2, int N, int SZ> struct HashMap { HashTable<T, N, SZ> ht; T2 b[SZ]; HashMap() { clear(); } void clear() { ht.clear(); up(i, SZ) b[i]=T2(); } void insert(pair<T, T2> p) { b[ht.add(p.first)] = p.second; } int find(T key) { return ht.find(key); } T2 get(T key) { return b[ht.find(key)]; } T2& operator[] (T key) { int ac = find(key); if (~ac) return b[ac]; else return b[ht.add(key)]; } };
相关文章推荐
- online_judge_1121
- ucosIII 事件标志组、同时等待多个内核对象、存储管理
- UITableView---总结
- ylbtech-Unitity-CS-Arrays:数组
- 软工实践总结
- Android屏幕适配
- Android system
- 2.未公开的Oracle数据库秘密笔记——参数说明——PGA_AGGREGATE_TARGET
- 第3章 UI
- 使用java递归实现文件及文件夹的复制
- POJ-1322 Chocolate(概率DP)
- VIM私人配置
- POJ-1322 Chocolate(概率DP)
- poj River Hopscotch 3258 (二分)好题
- iOS Objective-c的MD5/SHA1加密算法的实现
- Android-socket-client客户端<2>
- NEU 1666 字符串游戏(巧用map)
- 黑马程序员——字符串
- hdu 1151 &&poj 1422 Air Raid (二分图匹配 最小路径覆盖)
- Android webview使用详解