看数据结构写代码(61) 哈希表
来源:互联网 发布:企业级网管软件 编辑:程序博客网 时间:2024/05/22 04:47
前面说的 各种查找都是 基于 “比较” 的基础 来进行 查找的。查找的 效率 要 看 比较的 次数。那么 有没有 不需要 比较,就可以 找到 想要的数据的 方法呢?
哈希表 就是 这样的 一种方法,它用 数组 作为 保存 关键字的 数据原型,通过 一个 哈希 函数f(k),来找到 关键字 存储的位置,从而 找到想要的信息。
例如 我们 想要解决 这样的一个问题:
假设这有一个各种字母组成的字符串,假设这还有另外一个字符串,而且这个字符串里的字母数相对少一些。什么方法能最快的查出所有小字符串里的字母在大字符串里都有?
比如,如果是下面两个字符串:
String 1: ABCDEFGHLMNOPQRS
String 2: DCGSRQPOM
我们 可以用 一个 分配 一个 26 个 int 型的 整形数组 a,将 0~25 分别 代表 A~Z 是否 出现,如果 出现则 值为 1,没有出现 值为0.
则 我们 只需 遍历 String1,然后 将 对应的 元素 设置 为1,然后 遍历 String2 ,如果 查找 过程中 ,遇到了 0 值, 则 不是 。否则 String2 的 字母 在 String1 中 都 存在。
哈希表 虽然 快速,但是 其 数据 原型 基于 数组,同样 有缺陷。
当 查找的 元素 集合 太大,不同的 关键字,却 得到 同样的 地址。即 k1 != k2,, F(K1) = = F(K2),这时 叫做 冲突。冲突 是无法避免的。只能 通过一些方法 减少 冲突。当 我们 插入 元素时,寻找 插入位置,造成的 冲突次数 太多,影响查找效率,我们 只能 重新 建表,这是个 费时的过程。
而且 哈希 是 无法 按 从小到 大 遍历 数据的。
所以 我们在 用哈希的时候得考虑这些:
1.哈希函数
2冲突函数
3初始表长
4冲突多少次,我们就重新建表,
5.是否需要 顺序遍历。
下面代码 用的是
哈希函数:除整取余法
冲突函数:开发定址法(线性)
冲突次数 到达 表长的一半 就重新建表。
哈希表基本结构 ,初始化 和销毁
#include "stdafx.h"#include <cstdlib>int hashSize[] = {11,13,17,19};//哈希表容量增加 数组.#define NULL_KEY0struct HashTable{int * base;//数据的基址int count;//表的数量int sizeIndex;//表的容量大小的索引};void initHash(HashTable * t){t->sizeIndex =0;t->base = (int *)calloc(hashSize[t->sizeIndex],sizeof(int));t->count = 0;}void destoryHash(HashTable * t){free(t->base);t->base = NULL;t->sizeIndex = 0;t->count = 0;}
//除留余数法int hash(HashTable t,int key){return key % hashSize[t.sizeIndex];}
冲突函数:
//开发定址 线性探索解决冲突法int collision(HashTable t,int key,int times){return (key + times) % hashSize[t.sizeIndex];}
int search(HashTable t,int key,int * index,int *ctimes){*index = hash(t,key);*ctimes = 0;while (t.base[*index] != NULL_KEY && t.base[*index] != key){(*ctimes)++;*index = collision(t,key,*ctimes);}printf("------------查找%d, 查找了%d次--------------\n",key,*ctimes+1);if (t.base[*index] == key){return t.base[*index];}else{return NULL_KEY;}}
void reCreateHashTable(HashTable * t,int key);void insertHash(HashTable *t,int key){int index;//插入位置intctimes;//冲突次数int result = search(*t,key,&index,&ctimes);if (result == NULL_KEY && ctimes < hashSize[t->sizeIndex]/2){//没找到t->base[index] = key;t->count ++;}else{//重新建表reCreateHashTable(t,key);}}//void reCreateHashTable(HashTable * t,int key){printf("--------------重建哈希表----------------\n");int * oldBase = t->base;//保存老空间.int oldSize = hashSize[t->sizeIndex];//老空间的容量大小t->sizeIndex++;int newSize = hashSize[t->sizeIndex];//新空间大小t->base = (int *) calloc(newSize,sizeof(int));//新空间//插入之前将 表的数量置0t->count = 0;for (int i = 0; i < oldSize; i++){if (oldBase[i] != NULL_KEY){insertHash(t,oldBase[i]);}}free(oldBase);//释放老空间insertHash(t,key);//插入冲突的关键字.}
测试函数:
static int testArray[10] = {1,18,7,55,23,45,98,76,35,29};int _tmain(int argc, _TCHAR* argv[]){HashTable table;initHash(&table);for (int i = 0; i < 10; i++){insertHash(&table,testArray[i]);}int index ,count;for (int i = 0; i < 10; i++){search(table,testArray[i],&index,&count);}destoryHash(&table);return 0;}
代码工程文件网盘地址:http://pan.baidu.com/s/1kToXLcj
- 看数据结构写代码(61) 哈希表
- 看数据结构写代码(4)单链表
- 看数据结构写代码(43) 关节点
- 看数据结构写代码(55) 二叉排序树
- 看数据结构写代码(65) 基数排序
- 看数据结构写代码(1) 三元组
- 看数据结构写代码(3)顺序表的 实现
- 看数据结构写代码(5)静态链表
- 看数据结构写代码(8)顺序栈的实现
- 看数据结构写代码(9)链栈的实现
- 看数据结构写代码(18) KMP算法
- 看数据结构写代码(19) 数组的实现
- 看数据结构写代码(41) 强连通分量
- 看数据结构写代码(42)最小生成树
- 看数据结构写代码(45) 拓扑排序
- 看数据结构写代码(46) 关键路径
- 看数据结构写代码(47)迪杰斯特拉最短路径算法
- 看数据结构写代码(48) 弗洛伊德最短路径
- Linux查看系统配置常用命令
- WEB架构师成长之路之三-架构师都要懂哪些知识
- banner广告及view pager 的小圆点指示器
- Java中SHA1加密算法
- 关键词快速排名至百度首页的技巧
- 看数据结构写代码(61) 哈希表
- intent
- 小波阈值去噪MATLAB代码
- 如何写出高效率的HTML
- ubuntu fix "the package system is broken"
- 一键分享到本地已有的软件上
- Oracle 小技巧
- 四大组件——Activity
- NGUI UIScrollView滑动视图的定位