目录

原理:

实例解释

存储逻辑图

需要的知识:

附加

完整代码

代码详解

执行结果

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. 【组队学习】【28期】青少年编程(Scratch 一级)
  2. c++常量函数的理解
  3. [HOW TO]-ubuntu20.04 上安装jenkins
  4. 升级到VS.net 2008 sp1并安装卡巴斯基的兄弟们小心了
  5. Faster-Rcnn的loss曲线可视化
  6. 【解题报告】Leecode 700. 二叉搜索树中的搜索——Leecode每日一题
  7. 中关村-DIY操作系统之不分区安装Ubuntu系统
  8. 数据结构——从叶子结点到根节点的全部路径
  9. 常见设计模式描术(看完就把它忘记~~)
  10. php图片上传报非法错误,老师,我在上传图片时,提示非法上传文件
  11. hihoCoder 1388(fft)
  12. js 的push 方法
  13. android tv tts,TTS发音问题
  14. 学习嵌入式单片机需要学习哪些内容?
  15. 第9周项目6委派任务
  16. matlab 去除最大值,TRIMMEAN 应用(求去掉最大或和最小值后的平均值的方法)
  17. c语言如何编辑一个长方形,C语言对象编程第一弹封装与抽象(建立长方形对象)...
  18. 相思子肯来,约在莲花岸。(模拟
  19. WPF 让窗口激活作为前台最上层窗口的方法
  20. git更新项目失败报错 protocol error: bad line length character: Acti

热门文章

  1. SQL Server将数据库的用户名映射到登录名
  2. c语言读取txt到一个字符串,c语言读取txt文件内容简单实例
  3. ArcGIS Server修改默认端口号
  4. 大数据分析:王宝强离婚事件到底有多火热!
  5. 实验四 交换机配置方式及基本命令的熟悉
  6. 根据电话号码获取联系人实例
  7. 跨年夜,想请你看一场烟花秀!
  8. 基于HyperMesh的钢筋有限元模型搭建
  9. 两种PDF页面大小不一致的调整办法
  10. 常见数据库时间戳格式化函数及用法(按时区格式化时间戳),java计算时区值