如何用C语言写一个散列表
发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,本篇文章为大家展示了如何用C语言写一个散列表,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、快速理解散列表散列表,就是下标可以为字母的数组。假设现有一个数组
千家信息网最后更新 2025年01月20日如何用C语言写一个散列表
本篇文章为大家展示了如何用C语言写一个散列表,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
一、快速理解散列表
散列表,就是下标可以为字母的数组。
假设现有一个数组int a[100],想查找其中第40个元素,则直接输入a[40]就可以了,时间复杂度为O ( 1 ) O(1)O(1)。
问题在于,当下标不是数字,而是一个字符串的时候,可能需要一个超大的空间才能将所有下标妥善地存放在特定的位置。例如,若以大小写字母作为下标索引,那么一位就需要预留52个空间,10位就需要52的10次方 这么大的空间,根本没有设备可以满足。
好在,52的10次方这么庞大的数字也超出了正常人的使用范围,无论多长的索引,我们能用上的值也绝对是有限的。
例如,现有下面三个字符串作为下标
key1 = "microcold";key2 = "tinycold";key3 = "microcool";
其实只需要选取头、尾两个字母,就能很好地区分这三个字符串,即
def hash(key): return key[0]+key[-1]
但这种算法对索引字符的要求非常高,至少头尾不能重复。所以,现在需要能把超长字符串映射成特定短字符串而且尽量避免重复的算法。
二、散列函数
最简单的散列函数就是求余,将输入字符串按位转为整数之后求余。由于在字符串可能会转成非常大的整数,故需了解余数的性质
(a+b)%c=(a%c+b %c)% c
相应地有:
(a*b)%c=((a%c)*(b %c))% c
用C语言实现如下:
#include#define MAXHASH 100//快速取幂法,a*b^n%cint PowerMod (int a, int b, int n, int c) { int ans = 1; b = b % c; while (n > 0) { if(n % 2 == 1) ans = (ans * b) % c; n = n / 2; //b >>= 1; b = (b * b) % c; } return (a*ans)%c; } int hash(char* key, int n){ int addr = 0; for(int i = 0; i < n; i++){ addr += PowerMod(key[i], 128, i, MAXHASH); } return addr%MAXHASH;}int main(){ char* str; int i; while(1){ gets(str); i = 0; while(str[i++]!='\0'){} printf("%d\n",hash(str,i)); } return 0;}
测试如下:
>gcc hash.c>a.exeasdf21microcold81tinycold12microcool5minicool81minicold73
三、防撞
尽管minicool和microcold撞车了,但通过100以内的位数,去表示52的9次方 的样本,也算是不错的表现了。
为了不发生撞车,则需更改数组中的元素类型——至少得是个结构体。而防止撞车的方法很简单,如果发生撞车,那我就不散列了,直接发配到一个指定的数组中。
#include#include #include #define MAXHASH 100typedef struct HASHNODE{ char *key; int next;} *hashNode;struct HASHNODE* hashTable[MAXHASH];struct HASHNODE* crashTable[MAXHASH]; //存储撞击之后的值int numCrash=0; //已有的撞击值void initTable(){ for(int i=0; i < MAXHASH; i++){ hashTable[i] = (hashNode)malloc(sizeof(struct HASHNODE)); hashTable[i]->key = NULL; hashTable[i]->next = -1; crashTable[i] = (hashNode)malloc(sizeof(struct HASHNODE)); crashTable[i]->key = NULL; hashTable[i]->next = -1; }}void insertCrash(char* str, int index, int n){ if(index == numCrash){ crashTable[numCrash]->key = (char*)malloc(sizeof(char)*n); strcpy(crashTable[numCrash++]->key, str); //此时新增一个节点 } else { if(crashTable[index]->next==-1) crashTable[index]->next = numCrash; insertCrash(str, hashTable[index]->next, n); }}//n为字符串长度void insertHash(char* str, int index,int n){ if(hashTable[index]->key==NULL){ hashTable[index]->key = (char*)malloc(sizeof(char)*n); strcpy(hashTable[index]->key, str); }else{ if(hashTable[index]->next==-1) hashTable[index]->next = numCrash; insertCrash(str, hashTable[index]->next, n); }}void printHash(){ for(int i = 0; i < MAXHASH; i++){ if(hashTable[i]->key!=NULL) printf("hashTable[%d]:%s\n",i,hashTable[i]->key); if(crashTable[i]->key!=NULL) printf("crashTable[%d]:%s\n",i,crashTable[i]->key); }}int PowerMod (int a, int b, int n, int c) { int ans = 1; b = b % c; while (n > 0) { if(n % 2 == 1) ans = (ans * b) % c; n = n / 2; //b >>= 1; b = (b * b) % c; } return (a*ans)%c; } int hash(char* key, int n){ int addr = 0; for(int i = 0; i < n; i++){ addr += PowerMod(key[i], 128, i, MAXHASH); } return addr%MAXHASH;}int main(){ initTable(); char* str; int i; while(1){ gets(str); if(strcmp(str,"exit")==0) break; i = 0; while(str[i++]!='\0'){} insertHash(str,hash(str,i),i); printf("%d\n",hash(str,i)); } printHash(); return 0;}
最后得到:
>gcc hash.c>a.exeasdf21hellworld84microcold81minicool81tinycool20tinycold12weixiaoleng11exitcrashTable[0]:minicoolhashTable[11]:weixiaolenghashTable[12]:tinycoldhashTable[20]:tinycoolhashTable[21]:asdfhashTable[81]:microcoldhashTable[84]:hellworld
可见一方面的确散列了,另一方面也的确防撞了。
上述内容就是如何用C语言写一个散列表,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。
字符
字符串
下标
数组
语言
字母
就是
空间
索引
三个
元素
内容
函数
技能
数字
整数
知识
算法
输入
防撞
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
是信息化建设和网络安全的坚强
网络安全工程师查找代码漏洞
杨浦区创新软件开发服务是什么
网络安全证书需要考什么
张家港软件开发多少钱
联想全球网络安全实验室
网络安全 可靠性
天津hp服务器虚拟化安装服务器
oracle数据库用户拷贝
网络安全之qq群
数据库外网地址端口怎么打开
网络安全审查办法讲解ppt
搭建unix服务器
mysql数据库实现乐观锁
韩国网站服务器
杭州蒲公英网络技术
网络技术在铁道
网络安全防护水平不断强化
传奇霸业人物升级数据库
网络慢会不会让数据库死锁
新融合服务器
运营商需要给软件开发商钱吗
网络安全教育个人信息有哪些
网络安全管理工作年鉴
网络安全宣传书法作品
南宁内网渗透网络安全
服务器能否扩充网口
松江区合格软件开发诚信合作
网络安全隔离 正向
铭创网络技术服务工作室