《数据结构》C++代码 散列表
2014-11-29 18:46
197 查看
散列表,又名哈希表、Hash表。这是一个神奇的数据结构,它的复杂度是常数级别,由于我非常喜欢这个数据结构,在此简单介绍一下。
(没有学过Hash表的同学,我推荐一个教程:http://www.cnblogs.com/jiewei915/archive/2010/08/09/1796042.html)
让我们回忆一下之前学过的数据结构,列个表,与Hash表做个比较(表中c表示常数):
这表中前四列很好理解(平衡树之所以给五颗星,是因为我假设大家树写得好看,如果代码不漂亮,恐怕多少颗星都有可能,甚至你写不对就是∞颗星……),而第五列新手可能比较陌生,这里解释一下。
例如你对N个元素写个无序结构,啥都不用想,存进去就好了;写个有序结构,也仅仅需要想想两个元素之间如何比大小即可(例如3<5、"ab"<"aca"),我们对这N个数本身的信息剖析得非常少。因此,像这种信息剖析度低的数据结构,你基本啥都不用想,拿来就可以写代码了。
但Hash表却并不是如此,我们需要对数据进行更深入的分析(例如数是不是整数、字符串有多长),否则你的Hash表就可能出错(例如有负数时,你直接去模)、复杂度退化为线性等等(例如很多数都是一个大素数K的整数倍,而你却正好选择了让每个数模K去Hash)。因此,养成分析数据的习惯,才能知道自己在具体题目中是否可以使用散列表、如何使用散列表。
好了,就介绍这么多。最后,既然我说Hash表的编程复杂度只有两颗星,那么下面给出我的代码(Hash表有很多种,除了裸Hash表之外,我最常用的就是大素数Hash+链表存重,代码简单而且适用性强):
题目:sjtuoj 1224
清爽版:Hash表的代码,清爽版对于新手来说很容易搞乱,因此仅给出类版。
类版:
1、裸Hash表(本题内存足够大,所以能过)
2、模大素数+拉链(对于本题来说,比较NC的做法,感谢HQ同学提示可以直接采用裸Hash表AC)
(没有学过Hash表的同学,我推荐一个教程:http://www.cnblogs.com/jiewei915/archive/2010/08/09/1796042.html)
让我们回忆一下之前学过的数据结构,列个表,与Hash表做个比较(表中c表示常数):
插入时间 | 删除时间 | 查找时间 | 编程复杂度 | 信息剖析度 | |
无序数组 | 1 | N | N | ☆ | ☆ |
有序数组 | N | N | logN | ☆ | ☆ |
无序链表 | 1 | N | N | ☆☆☆ | ☆ |
平衡树 | logN | logN | logN | ☆☆☆☆☆ | ☆ |
Hash表 | 常数 | 常数 | 常数 | ☆☆ | ☆☆☆ |
例如你对N个元素写个无序结构,啥都不用想,存进去就好了;写个有序结构,也仅仅需要想想两个元素之间如何比大小即可(例如3<5、"ab"<"aca"),我们对这N个数本身的信息剖析得非常少。因此,像这种信息剖析度低的数据结构,你基本啥都不用想,拿来就可以写代码了。
但Hash表却并不是如此,我们需要对数据进行更深入的分析(例如数是不是整数、字符串有多长),否则你的Hash表就可能出错(例如有负数时,你直接去模)、复杂度退化为线性等等(例如很多数都是一个大素数K的整数倍,而你却正好选择了让每个数模K去Hash)。因此,养成分析数据的习惯,才能知道自己在具体题目中是否可以使用散列表、如何使用散列表。
好了,就介绍这么多。最后,既然我说Hash表的编程复杂度只有两颗星,那么下面给出我的代码(Hash表有很多种,除了裸Hash表之外,我最常用的就是大素数Hash+链表存重,代码简单而且适用性强):
题目:sjtuoj 1224
清爽版:Hash表的代码,清爽版对于新手来说很容易搞乱,因此仅给出类版。
类版:
1、裸Hash表(本题内存足够大,所以能过)
2、模大素数+拉链(对于本题来说,比较NC的做法,感谢HQ同学提示可以直接采用裸Hash表AC)
#include // 裸Hash 类版 class Hash { int H[4000000]; int k(int num) { return num+2000000; } int num(int k) { return k-2000000; } public: Hash() { memset(H,0,sizeof(H)); } // 此代码中,由于这个Hash表比较大,会定义在全局,故无需初始化 void in(int num) { ++H[k(num)]; } int count(int num) { return H[k(num)]; } }; // 模大素数+拉链表 类版 class Hash { struct hash { int num; hash *next; }*H[250000],New[250000]; int L; hash* make(int num) { New[L].num=num; return New+L++; } int k(int num) { return (num+2000000)%249989; } public: Hash():L(0) { memset(H,0,sizeof(H)); } // 此代码中,由于这个Hash表比较大,会定义在全局,故无需初始化 void in(int num) { hash *u=make(num); u->next=H[k(num)]; H[k(num)]=u; } int count(int num) { int s=0; for(hash *u=H[k(num)];u;u=u->next) if(u->num==num) ++s; return s; } };
相关文章推荐
- 《数据结构》C++代码 散列表
- Android JNI 使用的数据结构JNINativeMethod详解 ||建立Android SDK下的JNI、JAVA应用完整步骤---Android JAVA调用C++代码
- C++代码,数据结构-最小生成树的两个算法,Prime&Kruskal
- C++代码,数据结构-内部排序-基数排序-链式基数排序
- 数据结构 - 希尔排序(Shell's Sort) 详解 及 代码(C++)
- 数据结构 - 表插入排序 详解 及 代码(C++)
- 数据结构+C++_№5_顺序表错误更正及新的代码
- 数据结构 - 简单选择排序(simple selection sort) 详解 及 代码(C++)
- C++代码,数据结构-内部排序-选择排序-堆排序
- C++代码,数据结构-内部排序-交换排序-快速排序
- 数据结构 - 快速排序(Quick Sort) 详解 及 代码(C++)
- C++代码,数据结构-连通图的关节点
- C++代码,数据结构-平衡二叉树
- C++代码,数据结构-二叉排序树
- C++代码,数据结构-内部排序-选择排序-归并排序
- [C++]数据结构:散列表HashTable的实现与简单应用
- C++代码,数据结构-广义表的遍历(非迭代,不用设栈)
- C++代码,数据结构-内部排序-插入排序-折半插入排序
- 数据结构 - 折半插入排序(Binary Insertion Sort) 详解 及 代码(C++)
- 【c/c++ 算法/数据结构】 邻接矩阵表示图,深度,广度优先遍历 算法设计+代码+图片