我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C语言写一个散列表

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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 <stdio.h>
#define MAXHASH 100

//快速取幂法,a*b^n%c
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(){
    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.exe
asdf
21
microcold
81
tinycold
12
microcool
5
minicool
81
minicold
73

三、防撞

尽管minicool和microcold撞车了,但通过100以内的位数,去表示52的9次方 的样本,也算是不错的表现了。

为了不发生撞车,则需更改数组中的元素类型——至少得是个结构体。而防止撞车的方法很简单,如果发生撞车,那我就不散列了,直接发配到一个指定的数组中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXHASH 100
typedef 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.exe
asdf
21
hellworld
84
microcold
81
minicool
81
tinycool
20
tinycold
12
weixiaoleng
11
exit
crashTable[0]:minicool
hashTable[11]:weixiaoleng
hashTable[12]:tinycold
hashTable[20]:tinycool
hashTable[21]:asdf
hashTable[81]:microcold
hashTable[84]:hellworld

可见一方面的确散列了,另一方面也的确防撞了。

到此这篇关于C语言写一个散列表的文章就介绍到这了,更多相关C语言写散列表内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C语言写一个散列表

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何用C语言写一个散列表

本篇文章为大家展示了如何用C语言写一个散列表,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、快速理解散列表散列表,就是下标可以为字母的数组。假设现有一个数组int a[100],想查找其中第40个
2023-06-22

C语言如何编写一个链表

这篇文章主要介绍了C语言如何编写一个链表,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。本文实例为大家分享了C语言编写一个链表的具体代码,具体内容如下链表具备的基本功能:1.创
2023-06-15

C语言如何实现一个链表队列

本篇内容主要讲解“C语言如何实现一个链表队列”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言如何实现一个链表队列”吧!C语言数据结构链表队列的实现1.写在前面  队列是一种和栈相反的,遵循先
2023-06-16

C语言代码:用 C 语言实现一个循环队列

本文将介绍如何使用C语言实现一个循环队列,包括队列的定义、入队、出队、判空和判满等操作。代码实现将遵循专业编程规范,并使用注释进行详细解释。

c语言怎么输入一个数列

如何使用 c 语言输入一个数列?使用标准输入函数 scanf(),指定 %d 格式占位符,逐个读取整数。使用 fgets() 读取整行输入,然后使用 sscanf() 将行解析为数字。使用 strtok() 分解字符串,并使用 atoi()
c语言怎么输入一个数列
2024-05-13

如何实现一个优秀的散列表!

假设现在有一篇很长的文档,如果希望统计文档中每个单词在文档中出现了多少次,应该怎么做呢?我们可以建一个HashMap,那HashMap是怎么做到高效统计单词对应数量的?我们下面会逐步来研究一下!

用c语言编写一个幂函数(c语言实现幂函数)

下面是一个使用C语言编写的幂函数的示例:```c#include double power(double base, int exponent){double result = 1.0;int i;if (exponent > 0){for
2023-09-22

C语言如何计算文件的 SHA-1 散列

本文介绍了使用C语言计算文件SHA-1散列的步骤,包括包含必需的库、打开文件、创建SHA-1上下文、读取文件并更新上下文、获取散列、转换为十六进制字符串和关闭文件。代码示例演示了这些步骤,此外还提供了注意事项,如确保安装OpenSSL库和输入正确的文件名。
C语言如何计算文件的 SHA-1 散列
2024-04-02

c语言单链表怎么写

单链表是一种线性数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。在 c 语言中,它可以用 struct 定义节点,并用指针表示链表。基本操作包括:创建链表在头部或末尾插入元素在头部、中间或末尾删除元素遍历链表C 语言单链表的实
c语言单链表怎么写
2024-05-21

C语言如何计算字符串的 SHA-1 散列

本文讲解了如何使用C语言中的OpenSSL库计算字符串的SHA-1散列值。通过五个步骤,从头文件包含到最终散列值的打印,详细介绍了计算过程。代码示例提供了实际用法,而优点和注意事项部分则提供了额外的见解。
C语言如何计算字符串的 SHA-1 散列
2024-04-02

利用C语言编写一个无限循环语句

这篇文章主要介绍了利用C语言编写一个无限循环语句问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-13

简单写一个计算机编程c语言

当然,下面是一个简单的C语言程序示例,用于计算两个整数的和:```c#include int main() { int num1, num2, sum; printf("请输入第一个整数:"); scan
2023-09-27

利用C语言编写一个扫雷游戏

本篇文章为大家展示了利用C语言编写一个扫雷游戏,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语言可以以简易的方
2023-06-06

使用c语言编写一个爱心效果

使用c语言编写一个爱心效果?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、说明用函数分别控制行间隔,输出*(爱心用*够成),换行。然后每个涵数内加一层循环,用数组控制循环次数
2023-06-15

利用C语言编写一个三子棋游戏

这篇文章给大家介绍利用C语言编写一个三子棋游戏,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。具体内容如下说明:该游戏的实现需要用到三个文件1、test.c:放置主函数(main())和菜单函数(menu())和游戏函数
2023-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录