返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >怎么使用C语言实现Hash表
  • 716
分享到

怎么使用C语言实现Hash表

2023-07-05 16:07:49 716人浏览 独家记忆
摘要

这篇“怎么使用C语言实现Hash表”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用C语言实现Hash表”文章吧。什么是

这篇“怎么使用C语言实现Hash表”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用C语言实现Hash表”文章吧。

    什么是Hash Table

    散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。

    散列函数

    散列函数是将我们想插入的节点散列成一个数值的函数。它是一个函数。我们可以把它定义成 hash(key),要想找到一个不同的 key 对应的散列值都不一样的散列函数,几乎是不可能的。即便像业界著名的MD5、SHA、CRC等哈希算法,也无法完全避免这种散列冲突。而且,因为数组的存储空间有限,也会加大散列冲突的概率。

    所以我们几乎无法找到一个完美的无冲突的散列函数,即便能找到,付出的时间成本、计算成本也是很大的,所以针对散列冲突问题,我们需要通过其他途径来解决。

    散列冲突

    开放寻址法

    开放寻址法的核心思想是,如果出现了散列冲突,我们就重新探测一个空闲位置,将其插入。那如何重新探测新的位置呢?我先讲一个比较简单的探测方法,线性探测(Linear Probing)。当我们往散列表中插入数据时,如果某个数据经过散列函数散列之后,存储位置已经被占用了,我们就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止。

    链表

    链表法是一种更加常用的散列冲突解决办法,相比开放寻址法,它要简单很多。我们来看这个图,在散列表中,每个“桶(bucket)”或者“槽(slot)”会对应一条链表,所有散列值相同的元素我们都放到相同槽位对应的链表中。

    HashMap 底层采用链表法来解决冲突。即使负载因子和散列函数设计得再合理,也免不了会出现拉链过长的情况,一旦出现拉链过长,则会严重影响 HashMap 的性能。

    于是,在 jdk1.8 版本中,为了对 HashMap 做进一步优化,我们引入了红黑树。而当链表长度太长(默认超过 8)时,链表就转换为红黑树。我们可以利用红黑树快速增删改查的特点,提高 HashMap 的性能。当红黑树结点个数少于 8 个的时候,又会将红黑树转化为链表。因为在数据量较小的情况下,红黑树要维护平衡,比起链表来,性能上的优势并不明显。

    装载因子

    装载因子越大,说明散列表中的元素越多,空闲位置越少,散列冲突的概率就越大。不仅插入数据的过程要多次寻址或者拉很长的链,查找的过程也会因此变得很慢。

    最大装载因子默认是 0.75,当 HashMap 中元素个数超过 0.75*capacity(capacity 表示散列表的容量)的时候,就会启动扩容,每次扩容都会扩容为原来的两倍大小。

    代码

    这里我们给出C语言的HashTable代码,我们使用的是链表法,而且也没有在链表过长的时候将其转化为红黑树,只是单纯的链表。

    #include <stdlib.h>#include <stdio.h>#include <stdbool.h>typedef struct node {    int key;    int val;    struct Node *next;} Node;typedef struct HashMap {    int size;    int count;    struct Node **hashmap;} HashMap;// 定义哈希函数unsigned int hash(int n) {    return (unsigned int) n;}// 创建一个节点Node *creatNode(int key, int val) {    Node *node = (Node *) malloc(sizeof(Node));    node->key = key;    node->val = val;    node->next = NULL;    return node;}// 创建一个hash表HashMap *createHashMap() {    HashMap *H = (HashMap *) malloc(sizeof(HashMap));    H->size = 8;    H->count = 0;    H->hashmap = (Node **) calloc(H->size, sizeof(Node *));    return H;}// 扩容,以2倍的形式扩容static void extend(HashMap *map) {    int newsize = map->size * 2;    Node **newhashmap = (Node **) calloc(newsize, sizeof(Node *));    for (int i = 0; i < map->size; i++) {        Node *node = map->hashmap[i];        Node *head1 = (Node *) malloc(sizeof(Node));        Node *head2 = (Node *) malloc(sizeof(Node));        Node *temp1 = head1;        Node *temp2 = head2;        while (node) {            if (hash(node->key) % newsize != i) {                temp2->next = node;                temp2 = temp2->next;            } else {                temp1->next = node;                temp1 = temp1->next;            }            node = node->next;        }        temp1->next = NULL;        temp2->next = NULL;        newhashmap[i] = head1->next;        newhashmap[i + map->size] = head2->next;        free(head1);        free(head2);    }    map->size = newsize;    free(map->hashmap);    map->hashmap = newhashmap;}// 插入某个结点bool insert(HashMap *map, int key, int val) {    int hash_key = hash(key) % map->size;    // 要插入的哈希值未产生碰撞    if (map->hashmap[hash_key] == NULL) {        map->count++;        map->hashmap[hash_key] = creatNode(key, val);    } else {        Node *head = map->hashmap[hash_key];        if (head->key == key) return false;        while (head->next && head->next->key != key) head = head->next;        if (head->next == NULL) {            map->count++;            head->next = creatNode(key, val);        } else if (head->next->key == key) return false;    }// 装载因子过高就开始扩容    if (map->count / map->size > 0.75) extend(map);    return true;}// 寻找某个结点bool find(HashMap *map, int key, int *v) {    int hash_key = hash(key) % map->size;    if (map->hashmap[hash_key] == NULL) {        return false;    } else {        Node *head = map->hashmap[hash_key];        if (head->key == key) {            *v = head->val;            return true;        }        while (head->next && head->next->key != key) head = head->next;        if (head->next == NULL) return false;        if (head->next->key == key) {            *v = head->next->val;            return true;        }    }    return false;}// 删除某个结点void delete(HashMap *map, int key) {    int hash_key = hash(key) % map->size;    if (map->hashmap[hash_key] == NULL) return;    Node *head = map->hashmap[hash_key];    if (head->key == key) {        map->hashmap[hash_key] = head->next;        map->count--;        free(head);        return;    }    while (head->next && head->next->key != key) head = head->next;    if (head->next == NULL) return;    if (head->next->key == key) {        Node *temp = head->next;        head->next = head->next->next;        map->count--;        free(temp);    }    return;}int main() {    HashMap *H = createHashMap();    for (int i = 0; i < 1024; i++) {        insert(H, i, i);    }    printf("H size is %d\n",H->size);    printf("H count is %d\n",H->count);    delete(H, 0);    int v = 0;    if (find(H, 0, &v)) printf("%d\n", v);    else printf("not find \n");    if (find(H, 4, &v)) printf("%d\n", v);    else printf("not find \n");    return 0;}

    以上就是关于“怎么使用C语言实现Hash表”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网其他教程频道。

    --结束END--

    本文标题: 怎么使用C语言实现Hash表

    本文链接: https://lsjlt.com/news/353224.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    猜你喜欢
    • 怎么使用C语言实现Hash表
      这篇“怎么使用C语言实现Hash表”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么使用C语言实现Hash表”文章吧。什么是...
      99+
      2023-07-05
    • Hash表怎么实现
      本篇内容介绍了“Hash表怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是Hash表Hash,一般翻译做“散列”,也有直接音译为...
      99+
      2023-06-02
    • C语言双链表怎么实现
      本篇内容介绍了“C语言双链表怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!定义链表是通过一组任意的存储单元来存储线性表中的数据元素,...
      99+
      2023-06-29
    • C语言手撕一个Hash表(HashTable)实例代码
      目录什么是Hash Table散列函数散列冲突开放寻址法链表法装载因子代码总结什么是Hash Table 散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种...
      99+
      2023-03-24
      c语言hash c语言实现哈希表 c语言hash表的实现
    • 怎么用C语言数组实现顺序表
      这篇文章主要讲解了“怎么用C语言数组实现顺序表”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么用C语言数组实现顺序表”吧!线性表和顺序表线性表线性表(linear list)是n个具有相同...
      99+
      2023-06-25
    • C语言的顺序表怎么实现
      本文小编为大家详细介绍“C语言的顺序表怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言的顺序表怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。1.线性表线性表(linear list)是n个具...
      99+
      2023-06-30
    • 怎么使用C语言实现计时器
      本篇内容主要讲解“怎么使用C语言实现计时器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用C语言实现计时器”吧!实现思路简单介绍一下我的实现思路:本文包括三个版本,分别是极简版、普通版、高...
      99+
      2023-06-25
    • 怎么使用C语言实现圣诞树
      要使用C语言实现圣诞树,你可以使用基本的输出函数 printf() 来打印出树的形状和装饰。下面是一个简单的示例代码:```c#include int main() {int height = 5; // 定义树的高度// 打印树的上半...
      99+
      2023-08-09
      C语言
    • C语言怎么实现循环双链表
      这篇文章主要介绍“C语言怎么实现循环双链表”,在日常操作中,相信很多人在C语言怎么实现循环双链表问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C语言怎么实现循环双链表”的疑惑有所帮助!接下来,请跟着小编一起来...
      99+
      2023-06-25
    • 怎么用c语言实现类
      在 c 语言中,类无法直接实现,但可以通过使用结构体、函数、指针和宏来模拟类行为。这种方式允许:使用结构体表示类的属性或字段。使用函数表示类的行为或方法。使用指针存储对结构体的引用,代表...
      99+
      2024-04-13
      c语言 c++ typedef
    • C语言实现实时钟表
      本文实例为大家分享了C语言实现实时钟表的具体代码,供大家参考,具体内容如下 一、最终效果展示 效果图如下: 二、绘制静态秒针 代码如下: #include<graphics...
      99+
      2024-04-02
    • C/C++使用C语言实现多态
      目录1.多态的概念1.1什么是多态?1.2为什么要用多态呢?1.3多态有什么好处?2.多态的定义及实现2.1继承中构成多态的条件2.2虚函数2.3虚函数的重写2.4C++11 ove...
      99+
      2024-04-02
    • C语言问号表达式怎么使用
      C语言中的问号表达式又称为条件表达式,它的语法如下:```expression1 expression2 : expression...
      99+
      2023-06-13
      问号表达式
    • C语言怎么实现顺序表的操作
      这篇文章主要介绍了C语言怎么实现顺序表的操作的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C语言怎么实现顺序表的操作文章都会有所收获,下面我们一起来看看吧。线性表线性表(linear list)是n个具有相同特...
      99+
      2023-06-30
    • C语言实现电子秒表
      秒表是我们生活中常见的计时工具,特别是在运动会等比赛中,今天我就来写一个简单的电子秒表。 实现思路 这里简单介绍一下我的实现思路: 1、简单版:简单版本只实现了单次计时功能,即每次开...
      99+
      2024-04-02
    • c语言链表如何实现
      这篇“c语言链表如何实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“c语言链表如何实现”文章吧。在计算机领域离不开算法和数...
      99+
      2023-06-19
    • c语言怎么实现类
      c 语言中实现类的途径有四种:结构体和函数指针:使用结构体封装数据和函数指针访问方法。宏和预处理器:宏定义类方法名,预处理器生成实现代码。编译器扩展:某些编译器支持面向对象编程扩展,允许...
      99+
      2024-04-13
      c语言 typedef
    • 怎么使用C语言实现音乐播放器
      本文小编为大家详细介绍“怎么使用C语言实现音乐播放器”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么使用C语言实现音乐播放器”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。介绍该程序是一个小的DEMO,实现了以...
      99+
      2023-07-05
    • 怎么用C语言链表实现销售管理系统
      这篇文章主要介绍“怎么用C语言链表实现销售管理系统”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么用C语言链表实现销售管理系统”文章能帮助大家解决问题。源码#include<stdio.h&...
      99+
      2023-06-29
    • C语言怎么实现链表与文件存取
      今天小编给大家分享一下C语言怎么实现链表与文件存取的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。此处为main函数的内容in...
      99+
      2023-06-30
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作