九种查找算法-哈希查找
哈希查找算法又称散列查找算法,是一种借助哈希表(散列表)查找目标元素的方法,查找效率最高时对应的时间复杂度为 O(1)。
哈希查找算法适用于大多数场景,既支持在有序序列中查找目标元素,也支持在无序序列中查找目标元素。讲解哈希查找算法之前,我们首先要搞清楚什么是哈希表。
哈希表是什么
哈希表(Hash table)又称散列表,是一种存储结构,通常用来存储多个元素。
和其它存储结构(线性表、树等)相比,哈希表查找目标元素的效率非常高。每个存储到哈希表中的元素,都配有一个唯一的标识(又称“索引”或者“键”),用户想查找哪个元素,凭借该元素对应的标识就可以直接找到它,无需遍历整个哈希表。
多数场景中,哈希表是在数组的基础上构建的,下图给大家展示了一个普通的数组:
哈希表:
我们使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素"分类",然后将这个元素存储在相应"类"所对应的地方。但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了"冲突",换句话说,就是把不同的元素分在了相同的"类"之中。后面我们将看到一种解决"冲突"的简便做法。
"直接定址"与"解决冲突"是哈希表的两大特点。
哈希函数:
规则:通过某种转换关系,使关键字适度的分散到指定大小的的顺序结构中,越分散,则以后查找的时间复杂度越小,空间复杂度越高。
算法思路:
如果所有的键都是整数,那么就可以使用一个简单的无序数组来实现:将键作为索引,值即为其对应的值,这样就可以快速访问任意键的值。这是对于简单的键的情况,我们将其扩展到可以处理更加复杂的类型的键。
用给定的哈希函数构造哈希表;
根据选择的冲突处理方法(常见方法:拉链法和线性探测法)解决地址冲突;
在哈希表的基础上执行哈希查找;
代码:
#include<stdio.h>
#include<stdlib.h>#define SUCCESS 1
#define UNSUCCESS 0
#define OVERFLOW -1
#define OK 1
#define ERROR -1
#define MAXNUM 9999 // 用于初始化哈希表的记录 keytypedef int Status;
typedef int KeyType;// 哈希表中的记录类型
typedef struct
{KeyType key;
}RcdType;// 哈希表类型
typedef struct
{RcdType *rcd;int size;int count;int *tag;
}HashTable;// 哈希表每次重建增长后的大小
int hashsize[] = { 11, 31, 61, 127, 251, 503 };
int index = 0;// 初始哈希表
Status InitHashTable(HashTable &H, int size)
{int i;H.rcd = (RcdType *)malloc(sizeof(RcdType)*size);H.tag = (int *)malloc(sizeof(int)*size);if (NULL == H.rcd || NULL == H.tag) return OVERFLOW;KeyType maxNum = MAXNUM;for (i = 0; i < size; i++){H.tag[i] = 0;H.rcd[i].key = maxNum;}H.size = size;H.count = 0;return OK;
}// 哈希函数:除留余数法
int Hash(KeyType key, int m)
{return (3 * key) % m;
}// 处理哈希冲突:线性探测
void collision(int &p, int m)
{p = (p + 1) % m;
}// 在哈希表中查询
Status SearchHash(HashTable H, KeyType key, int &p, int &c)
{p = Hash(key, H.size);int h = p;c = 0;while ((1 == H.tag[p] && H.rcd[p].key != key) || -1 == H.tag[p]){collision(p, H.size); c++;}if (1 == H.tag[p] && key == H.rcd[p].key) return SUCCESS;else return UNSUCCESS;
}//打印哈希表
void printHash(HashTable H)
{int i;printf("key : ");for (i = 0; i < H.size; i++)printf("%3d ", H.rcd[i].key);printf("\n");printf("tag : ");for (i = 0; i < H.size; i++)printf("%3d ", H.tag[i]);printf("\n\n");
}// 函数声明:插入哈希表
Status InsertHash(HashTable &H, KeyType key);// 重建哈希表
Status recreateHash(HashTable &H)
{RcdType *orcd;int *otag, osize, i;orcd = H.rcd;otag = H.tag;osize = H.size;InitHashTable(H, hashsize[index++]);//把所有元素,按照新哈希函数放到新表中for (i = 0; i < osize; i++){if (1 == otag[i]){InsertHash(H, orcd[i].key);}}return OK;
}// 插入哈希表
Status InsertHash(HashTable &H, KeyType key)
{int p, c;if (UNSUCCESS == SearchHash(H, key, p, c)){ //没有相同keyif (c*1.0 / H.size < 0.5){ //冲突次数未达到上线//插入代码H.rcd[p].key = key;H.tag[p] = 1;H.count++;return SUCCESS;}else recreateHash(H); //重构哈希表}return UNSUCCESS;
}// 删除哈希表
Status DeleteHash(HashTable &H, KeyType key)
{int p, c;if (SUCCESS == SearchHash(H, key, p, c)){//删除代码H.tag[p] = -1;H.count--;return SUCCESS;}else return UNSUCCESS;
}int main()
{printf("-----哈希表-----\n");HashTable H;int i;int size = 11;KeyType array[8] = { 22, 41, 53, 46, 30, 13, 12, 67 };KeyType key;//初始化哈希表printf("初始化哈希表\n");if (SUCCESS == InitHashTable(H, hashsize[index++])) printf("初始化成功\n");//插入哈希表printf("插入哈希表\n");for (i = 0; i <= 7; i++){key = array[i];InsertHash(H, key);printHash(H);}//删除哈希表printf("删除哈希表中key为12的元素\n");int p, c;if (SUCCESS == DeleteHash(H, 12)){printf("删除成功,此时哈希表为:\n");printHash(H);}//查询哈希表printf("查询哈希表中key为67的元素\n");if (SUCCESS == SearchHash(H, 67, p, c)) printf("查询成功\n");//再次插入,测试哈希表的重建printf("再次插入,测试哈希表的重建:\n");KeyType array1[8] = { 27, 47, 57, 47, 37, 17, 93, 67 };for (i = 0; i <= 7; i++){key = array1[i];InsertHash(H, key);printHash(H);}getchar();return 0;
}
九种查找算法-哈希查找相关推荐
- 查找算法06-哈希查找
查找算法06-哈希查找 6.哈希查找 6-1实现代码 6-2测试 6-3方法解析 知识分享: 热门博客 6.哈希查找 (1)概述 在哈希表中,若出现key1≠key2,而f(key1)=f(key2) ...
- python实现顺序查找和哈希查找算法
顺序查找 顺序查找是按照序列原有顺序对数组进行遍历比较查询的基本查找算法,顺序查找是最简单的搜索算法,其实现如下: def sequential_search(items, item):for i i ...
- 数据结构和算法系列13 五大查找之哈希查找
原文地址 http://www.cnblogs.com/mcgrady/p/3294871.html 数据结构和算法系列13 五大查找之哈希查找 这一篇要总结的是五天查找的最后一篇,哈希查找,也称为散 ...
- python 查找算法_七大查找算法(Python)
查找算法 -- 简介 查找(Searching)就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素. 查找表(Search Table):由同一类型的数据元素构成的集合 关键字(Ke ...
- C/C++折半查找与哈希查找[2023-05-11]
C/C++折半查找与哈希查找[2023-05-11] 4.折半查找与哈希查找(难度等级 A) [问题描述] 查找是通过在查找表中做比较来完成的操作.折半查找与哈希查找都是利用数组实现的查找算法.通过本 ...
- 查找算法:二分查找、顺序查找
08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活.此系列是对四年专业课程学习的回顾,索引参见:http://blog.csdn.net/xiaowei_cqu/article/de ...
- 非常值得一看—九种滤波算法C语言实现
关注"嵌入式软件开发学习圈"免费获取更多学习教程 今天带着大家学习滤波算法c语言(九种滤波算法)实现,以及代码,大家可以学习了解下.... 1.限幅滤波算法(程序判断滤波算法) 方 ...
- 数据结构之查找算法:分块查找
查找算法:分块查找 思维导图: 分块查找的定义: 如何分块: 如何查找: 代码实现: 查找效率: 思考: 思维导图: 分块查找的定义: 如何分块: 例: 如何查找: 1.先查找在哪块 2.然后查找块内 ...
- 数据结构之查找算法:折半查找
查找算法:折半查找 思维导图: 算法思想: 代码实现: 判定树: 折半查找判定树的构造: 顺序查找与折半查找对比: 思维导图: 算法思想: 代码实现: typedef struct {int *ele ...
最新文章
- C#图片处理常见方法性能比较
- QTP11补丁下载 – 完美支持FIREFOX 9~10
- c++网络通信(与服务器通信聊天)和c#网络通信
- 软考-信息系统项目管理师-流程管理
- 消息队列概述[幻灯片]
- 单元测试原来是这样的呼
- “背叛”乔布斯,库克做对了
- 聊一聊晋升带来的思考
- 计算机网络 chapter 6 应用层
- 相位编码信号 matlab,matlab 求基于相位编码的雷达回波仿真 更多交易加我QQ
- Nginx 解决 Tomcat 集群下的 Session共享
- 新功能,赶紧用起来,CSDN浏览器助手-脚本功能,兼容油猴脚本安装使用
- 什么是CPU虚拟化?打开好还是关闭好?
- PLM与PDM的概念与区别
- python:汽水瓶
- python实现 Python蟒蛇绘制(嵩天老师 )
- 报表引擎终于做出来了!!!
- 理解块存储、文件存储和对象存储的应用场景和选择
- float单精度浮点和double双精度浮点
- 电脑的字体改变了、变模糊了怎么办