目录

原理:

实例解释

存储逻辑图

需要的知识:

附加

完整代码

代码详解

执行结果

1.查找个不存在的

2.查找个存在的


原理:

一个指针数组,来存储 每个链表的头节点首地址

如果要从 'NUM' 个数中查找数据
先对'NUM'/0.75,求得最大质数'N'        //(质数:只能被1和本身整除的数)
然后创建一个有'N'个元素'指针数组'
然后将'NUM'个数分别对'N'取余
将每一个数保存在'余数'等于数组元素下标链表
然后进行查找是直接找对应的数组下标即可

实例解释

如果要从11个数中查找数据
然后11/0.75=14,求得最大质数13
然后创建一个有13个元素的'指针数组'
然后将'11个数'分别对'13取余'
将每一个数保存在'余数'等于'数组元素下标'的链表中        //---需要链表
然后进行查找是直接找对应的数组下标即可

存储逻辑图

需要的知识:

质数:只能被1和本身整除的数
指针数组本质是个数组,数组里存的是指针
链表的操作:
    创建:
    遍历:
    增删改查:
    释放:free
malloc:主动申请堆区空间        //(返回值类型)malloc(申请的空间的大小)
int类型:4个字节
指针类型:4个字节(32位系统),8个字节(64位系统)

附加

哈希表查找算法的时间复杂度为O(n^1)

HASH查找效率高的原因

查找某一个数,先求出这个数的余数,然后根据余数直接定位到对应的链表地址,然后在该链表里查找(链表里只有几个数据)--所以快!!

完整代码

#include <stdio.h>
#include <stdlib.h>#define N 13
#define ADDR_SIZE 8 //hash表的链表的节点
typedef struct node {int data;//存数据struct node *next;//存指针
}HASH;//创建hash表
HASH **create_hash()
{HASH **h = (HASH **)malloc(N * ADDR_SIZE);int i = 0;for (i = 0; i < N; i++){h[i] = (struct node *)malloc(sizeof(struct node));h[i]->next = NULL;}return h;
}//插入数据
int insert_hash_table(HASH **h, int data)
{int key = data % N; struct node * p = h[key];//头插法插入数据struct node * temp;temp = (struct node *)malloc(sizeof(struct node));temp->data = data;temp->next = p->next;p->next = temp;return 0;
}//遍历
int show_hash_table(struct node *head)
{//如果链表后面没有数据,则用---0---表示链表存在但是没有数据if (head->next == NULL){puts("---0---");return -1;}//遍历链表,打印数据while(head->next != NULL){head = head->next;printf("%d ", head->data);}putchar(10);return 0;
}//释放链表节点
int free_hash_table(struct node *head)
{//如果链表后面没有数据,则无需释放if (head->next == NULL){return 0;}   //遍历这个链表-头删法释放while(head->next != NULL){//定义一个结构体指针变量 来指向这个即将被删除的结构体 以便释放        struct node *temp = head->next;head->next = head->next->next;printf("--%d--将被释放\n",temp->data);free(temp);temp = NULL;}return 0;
}//查找数据
int search_hash_table(HASH **h, int data)
{int key = data % N; //数据对质数取余,得到键值struct node *p = h[key]; //找到对应链表//对比要查找的数据while (p->next != NULL ){if (p->next->data == data){ return 1;//找到返回1}p = p->next;}//没有找到返回0return 0;
}//11个数据,那么m : n/0.75 = 14, 最大质数为13
int main(int argc, const char *argv[])
{int a[11] = {100, 34, 14, 45, 46, 98, 68, 69, 7, 31, 26};//创建hash表HASH **h = create_hash();int i = 0;int num = 0;for (i = 0; i < 11; i++){insert_hash_table(h, a[i]);//链表的插入}//打印hash表--无实际意义printf("-------这是hash表--------------------\n");for (i = 0; i < N; i++){show_hash_table(h[i]);//链表的遍历}printf("--------hash表结束--------------------\n");printf("数组数据如下-->用于测试,无实质意义,遍历HASH表也是<---\n");for(i = 0;i < 11;i ++){printf("%d  ",a[i]); }putchar(10);printf("please input need 查找 de number >>");scanf("%d",&num);//--查找--if(search_hash_table(h, num) == 1){printf("---data %d is exists---\n", num); }else{printf("---data %d is not exists---\n", num);}//链表的释放for(i = 0;i < 11;i ++){free_hash_table(h[i]);}printf("---链表释放完成---\n");free(h);printf("---指针数组释放---\n");return 0;
}

代码详解

#include <stdio.h>
#include <stdlib.h>#define N 13       //余数:也是指针数组的元素个数:也是链表的个数
#define ADDR_SIZE 8 //这个定义的是 指针数组的 每个指针的大小,(64位系统)8个字节//hash表 链表的节点
typedef struct node {int data;//存数据struct node *next;//存指针
}HASH;//类型重命名-->HASH//创建hash表(创建了十三个链表头节点)
HASH **create_hash()
{//申请创建一个指针数组,存13个头节点//先创建一个指针数组,指针数组可以在栈区申请(int *h[]),但是当前函数结束会被释放 //所以在堆区申请空间,指针数组的返回值 是二级指针 所以用HASH **h来接收//这块申请了一个 有13个位置的指针数组HASH **h = (HASH **)malloc(N * ADDR_SIZE);//(返回值类型)malloc(申请的空间的大小)int i = 0;//这块要填充这个指针数组//创建链表的头结点--先malloc申请出来一个头节点,分别把他们放到指针数组h[0]--h[12] 里for (i = 0; i < N; i++){h[i] = (struct node *)malloc(sizeof(struct node));//创建头节点h[i]->next = NULL;//初始化头节点 指针域} //注意:再此申请的节点 都被保存到 (指针数组)h 里了return h;
}//插入数据
int insert_hash_table(HASH **h, int data)//参数:指针数组,需要插入的数据
{//然后将'需要插入的数据'对'质数13取余'--确定好数据对应的 指针数组下标//找到指定的链表int key = data % N; //根据指针数组的下标,确定对应的链表的头节点,//定义了一个结构体指针变量p 指向 指针数组的第[key]位对应的 链表struct node *p = h[key];//也可以直接操作h[key],定义一个指针好理解点//--头插法--插入数据struct node *temp;//定义了一个 结构体指针变量temp = (struct node *)malloc(sizeof(struct node));//malloc申请空间temp->data = data;//初始化一下//头插法 插入temp->next = p->next;//新定义节点的指针域 指向 头节点的下一个节点p->next = temp;//头节点的指针域,指向新定义的节点return 0;
}//打印排好的hash表--遍历
int show_hash_table(struct node *head)//参数:对应链表的头节点--main函数多次调用
{//如果链表后面没有数据,则用---0---表示链表存在但是没有数据if (head->next == NULL){puts("---0---");return -1;}//如果链表后面有数据,遍历链表,打印数据while(head->next != NULL){   //由于头节点没有数据,所以,先移动指针,然后输出数据head = head->next;printf("%d  ", head->data);}putchar(10);//输出个换行符return 0;
}
//释放链表节点
int free_hash_table(struct node *head)
{//如果链表后面没有数据,则无需释放if (head->next == NULL){return 0;}   //遍历这个链表-头删法释放while(head->next != NULL){//定义一个结构体指针变量 来指向这个即将被删除的结构体 以便释放struct node *temp = head->next;head->next = head->next->next;//改变头结点指针域指向,删除节点printf("--%d--将被释放\n",temp->data);free(temp);//释放temp = NULL;//置空(防止被别的函数修改)}return 0;
}
//查找数据
int search_hash_table(HASH **h, int data)//参数:指针数组,需要查找的数据
{int key = data % N; //先把要查找的数据对 质数 取余,得到对应的下标struct node *p = h[key]; //根据下标找到对应链表,定义了一个结构体指针变量p,指向该链表//--循环遍历--对比--//循环遍历的结束条件是,p->next 域 为空(NULL)while (p->next != NULL){if (p->next->data == data){    return 1;//找到返回1}p = p->next;//移动指针}//没有找到返回0return 0;
}//程序的入口:
//假定数组有11个元素--> 11/0.75 ==> 14.67 ==> 最大质数 为 13
int main(int argc, const char *argv[])
{int a[11] = {100, 34, 14, 45, 46, 98, 68, 69, 7, 31, 26};//直接初始化了11个数值的数组//创建hash表HASH **h = create_hash();//为啥用二级指针:指针数组的返回值是二级指针//将数据按照格式插入到链表中int i = 0;int num = 0;//链表增加--多次调用-插入数组a的每个元素for (i = 0; i < 11; i++)//给 a[i] 使的{insert_hash_table(h, a[i]); //链表的插入}printf("-------这是hash--------------------\n");    //打印hash表--打印每个指针数组元素所存储的链表for (i = 0; i < N; i++){show_hash_table(h[i]);//链表的遍历}printf("--------hash表结束--------------------\n");printf("数组数据如下-->用于测试,无实质意义,遍历HASH表也是<---\n");for(i = 0;i < 11;i ++){printf("%d  ",a[i]);   }putchar(10);//  while(1)
//  {//查找printf("please input need 查找 de number >>");scanf("%d",&num);//由于输入字母,会造成死循环,所以也可以用char类型定义,或者加个判断(ASCII码)//指定数据判断是否存在-----查找if(search_hash_table(h, num) == 1){printf("---data %d is exists---\n", num); }else{printf("---data %d is not exists---\n", num);}
//  }//链表的释放for(i = 0;i < 11;i ++){free_hash_table(h[i]);}printf("---链表释放完成---\n");free(h);printf("---指针数组释放---\n");return 0;
}

执行结果

1.查找个不存在的

2.查找个存在的

C语言-哈希查找(HASH)-详解(完整代码)相关推荐

  1. C语言【二分查找】详解

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 二分 文章目录 前言 一.[二分查找]的步骤 二.[二分查找]的注意事项 三.举例详解[二分查找] 前言 一.[二分查找]步骤 二.[ ...

  2. c语言实现蛇形矩阵(详解含代码)

    大家好,我是诚挚的乔治  前言: 本次蛇形矩阵我将以两种方法来实现,即非递归和递归 非递归的实现: #define right 1 #define down 2 #define left 3 #def ...

  3. Spring MVC+Spring+Mybatis实现支付宝支付功能(图文详解+完整代码)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 来源:欧阳思海 github.com/OUYANGSIHAI/si ...

  4. SSM 实现支付宝支付功能(图文详解+完整代码)

    阅读本文大概需要 4 分钟. 前言 本教程详细介绍了如何使用ssm框架实现支付宝支付功能.本文章分为两大部分,分别是「支付宝测试环境代码测试」和「将支付宝支付整合到ssm框架」,详细的代码和图文解释, ...

  5. Spring MVC+Spring+Mybatis实现支付宝支付和微信支付功能(图文详解+完整代码)

    前言 本教程详细介绍了如何使用ssm框架实现支付宝支付功能.本文章分为两大部分,分别是「支付宝测试环境代码测试」和「将支付宝支付整合到ssm框架」,详细的代码和图文解释,自己实践的时候一定仔细阅读相关 ...

  6. 一致性哈希算法原理详解

    一.普通 hash 算法 (取模算法): 在了解一致性哈希算法之前,我们先了解一下缓存中的一个应用场景,了解了这个应用场景之后,再来理解一致性哈希算法,就容易多了,也更能体现出一致性哈希算法的优点,那 ...

  7. php函数find的用法,c语言find函数的用法详解

    c语言find函数的用法详解 C语言之find()函数 find函数用于查找数组中的某一个指定元素的位置. 比如:有一个数组[0, 0, 5, 4, 4]: 问:元素5的在什么位置,find函数 返回 ...

  8. c语言线性表库函数大全,数据结构(C语言版)-线性表习题详解

    <数据结构(C语言版)-线性表习题详解>由会员分享,可在线阅读,更多相关<数据结构(C语言版)-线性表习题详解(23页珍藏版)>请在人人文库网上搜索. 1.数 据 结 构 ,线 ...

  9. C语言 计算选手的名次 详解

    C语言 计算选手的名次 详解 我是JaYLove0589. 本着程序员互相学习的原则, 且因自己深受此题困扰,对递归函数的使用不熟练,所以发下面代码. 望大家指正. 题目描述: 5位选手参加100米决 ...

最新文章

  1. 语义分割网络经典:unet
  2. u盘安装centos8黑屏_崩溃!电脑突然黑屏无法启动
  3. 无比震荡 Fedora Linux把密码输出都落实起来
  4. 服务器2012r2系统安装数据库,数据库图文详解Windows Server2012 R2中安装SQL Server2008...
  5. hp designiet 500绘图仪程序_邹军:通过数控宏程序实现刀具寿命管理
  6. ClassFinal 加密 Java class文件工具
  7. mac连接Linux工具推荐,mac最值得关注的终端工具,你知道几个?
  8. 单龙芯3A3000-7A1000PMON研究学习-(2)搭建交叉编译环境
  9. python e_python 常数e
  10. 箱形图(python画图)
  11. 安装hue一直失败,请大佬帮帮忙,万分感谢!!!!!!!!
  12. 第一章图像处理基础概念(人眼和光)
  13. 工作站和微型计算机的区别,轻松了解工作站和台式机的区别,用Precision 3551挥洒创意...
  14. android 动态定制模板,android studio 自定义模板
  15. 越狱Season 1-Episode 14: The Rat
  16. 解决 IDEA2022 push远程时取消analyze code后,退出后自动复原
  17. 搜狗输入法android皮肤,搜狗输入法皮肤盒子app
  18. MariaDB 开源下的商业化征途
  19. Java 左移运算符注意事项
  20. 芯片STC89C52 (宏晶STC)

热门文章

  1. 【工程实践】飞马SLAM100三维数据处理
  2. docker搭建pxc
  3. python支持哪些数据类型_Python支持的数据类型
  4. 大亚湾核电基地累计对港供电达2488亿度
  5. Gradle配置SpringBoot多环境打包
  6. mpvue catchtap 的使用 以及 自定义弹出层 拦截上下滑动
  7. 我的世界java要哪个版本_我的世界网易 Java 版哪个版本比较好?
  8. python 训练好的模型怎么保存_如何保存训练好的机器学习模型
  9. 月入万元和月入千元,要认清,做自媒体和抖音哪个更适合新手?
  10. Bag Of Features(BOF)图像检索方法