哈希表的主要用处:快速的数据存储和查找。例如,在我们日常上网过程中搜索某条信息的时候,信息的存储方式决定了查找该信息的速度,哈希表结合了数组的便捷访问和链表的便捷查找和删除的特点。

实现方式:通过哈希函数获取哈希表的地址,遇到冲突的情况下采用拉链法解决冲突。

时间复杂度O(1)

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

/*定义哈希表数组的长度*/

#define BUCKETCOUNT 16

/*哈希表结点数据结构定义*/

struct hashEntry

{

char *key;

char *value;

struct hashEntry *next;

};

typedef struct hashEntry entry;

struct hashTable

{

entry bucket[BUCKETCOUNT];/*先默认定义16个桶*/

};

typedef struct hashTable table;

/*初始化哈希表*/

void initHashTable(table *t)

{

int i;

if(!t)

return;

for(i = 0; i < BUCKETCOUNT; ++i)

{

t->bucket[i].key = NULL;

t->bucket[i].next = NULL;

t->bucket[i].value = NULL;

}

}

/*散列函数*/

int keyToIndex(const char *key)

{

int index, len, i;

if(key == NULL)

return -1;

len = strlen(key);

index = (int)key[0];

for(i = 1; i < len; ++i)

{

index *= 1103515245 + (int)key[i];

}

index >>= 27;

index &= (BUCKETCOUNT - 1);

return index;

}

/*在堆上分配足以保存str的内存,并拷贝str的内容到新分配的位置*/

char *strDup(const char *str)

{

int len;

char *ret;

if(!str)

return NULL;

len = strlen(str);

ret = (char *)malloc(sizeof(len + 1));

if(!ret)

return NULL;

memcpy(ret, str, len);

ret[len] = '0';

return ret;

}

/*插入数据到hash表中*/

int insertEntry(table *t, const char *key, const char *value)

{

int index, vlen1, vlen2;

entry *e, *ep;

if(t == NULL || key == NULL || value == NULL)

return -1;

index = keyToIndex(key);

if(!t->bucket[index].key)

{

t->bucket[index].key = strDup(key);

t->bucket[index].value = strDup(value);

}

else

{

e = ep = &(t->bucket[index]);

/*先从已经存在的找*/

while(e)

{

/*找到key所在的位置,替换相应的值*/

if(strcmp(e->key, key) == 0)

{

vlen1 = strlen(value);

vlen2 = strlen(e->value);

if(vlen1 > vlen2)

{

free(e->value);

e->value = (char *)malloc(sizeof(vlen1 + 1));

}

memcpy(e->value, value, vlen1 + 1);

return index;/*插入完成*/

}

ep = e;

e = e->next;

}

/*没有在当前桶中找到,创建条目加入*/

e = (entry *)malloc(sizeof(entry));

e->key = strDup(key);

e->value = strDup(value);

e->next = NULL;

ep->next = NULL;

}

return index;

}

/*找到哈希表中key对应的entry,找到之后返回对应的entry,并将其删除*/

/*没找到返回NULL*/

entry *removeEntry(table *t, char *key)

{

int index;

entry *e, *ep;

if(!t || !key)

return NULL;

index = keyToIndex(key);

e = &(t->bucket[index]);

while(e)

{

if(strcmp(e->key, key) == 0)/*如果是桶的第一个*/

{

if(e == &(t->bucket[index]))

{

ep = e->next;

if(ep)

{

entry *tmp = e;

e = ep;

ep = tmp;

ep->next = NULL;

}

else/*这个桶只有一个元素*/

{

//ep = (entry*)malloc(sizeof(entry));

ep = e;

e->key = e->value = NULL;

e->next = NULL;

}

return ep;

}

}

else/*如果不是木桶第一个元素*/

{

//找到它的前一个

ep = t->bucket[index].next;

while((ep->key != key) && ep)

{

ep = ep->next;

}

if(!ep)

return NULL;

return ep;

}

e = e->next;

}

return NULL;

}

/*打印hash表*/

void printTable(table *t)

{

int i;

entry *e;

if(!t)

return;

for(i = 0; i < BUCKETCOUNT; i++)

{

printf("nbucket[%d]:n", i);

e = &(t->bucket[i]);

while(e)

{

printf("t%st = t%sn",e->key, e->value);

e = e->next;

}

}

}

/*释放哈希表*/

void freeHashTable(table* t)

{

int i;

entry* e,*ep;

if (t == NULL)return;

for (i = 0; i<BUCKETCOUNT; ++i) {

e = &(t->bucket[i]);

while (e->next != NULL) {

ep = e->next;

e->next = ep->next;

free(ep->key);

free(ep->value);

free(ep);

}

}

}

int main(void)

{

table t;

initHashTable(&t);

insertEntry(&t , "电脑型号" , "华硕 X550JK 笔记本电脑");

insertEntry(&t , "操作系统" , "Windows 8.1 64位 (DirectX 11)");

insertEntry(&t , "处理器" , "英特尔 Core i7 - 4710HQ @ 2.50GHz 四核");

insertEntry(&t , "主板" , "华硕 X550JK(英特尔 Haswell)");

insertEntry(&t , "内存" , "4 GB(Hynix / Hyundai)");

insertEntry(&t , "主硬盘" , "日立 HGST HTS541010A9E680(1 TB / 5400 转 / 分)");

insertEntry(&t , "显卡" , "NVIDIA GeForce GTX 850M (2 GB / 华硕)");

insertEntry(&t , "显示器" , "奇美 CMN15C4(15.3 英寸)");

insertEntry(&t , "光驱" , "松下 DVD - RAM UJ8E2 S DVD刻录机");

insertEntry(&t , "声卡" , "Conexant SmartAudio HD @ 英特尔 Lynx Point 高保真音频");

insertEntry(&t , "网卡" , "瑞昱 RTL8168 / 8111 / 8112 Gigabit Ethernet Controller / 华硕");

insertEntry(&t , "主板型号" , "华硕 X550JK");

insertEntry(&t , "芯片组" , "英特尔 Haswell");

insertEntry(&t , "BIOS" , "X550JK.301");

insertEntry(&t , "制造日期" , "06 / 26 / 2014");

insertEntry(&t , "主人" , "就是我");

insertEntry(&t , "价格" , "六十张红色毛主席");

insertEntry(&t , "主硬盘" , "换了个120G的固态");

entry *e = removeEntry(&t, "主板型号");

if(!e)

{

printf("不存在相关记录.n");

}

else

{

puts("释放记录结点的内存.");

free(e->key);

free(e->value);

free(e);

e = NULL;

}

printTable(&t);

freeHashTable(&t);

getchar();

return 0;

}

哈希桶 entry_哈希表代码实现相关推荐

  1. 哈希桶 entry_聊一聊面试常问的几大哈希算法问题,这些你都会了嘛??

    hashCode() 和equals() 方法的重要性体现在什么地方? Java中的HashMap使用hashCode()和equals()方法来确定键值对的索引,当根据键获取值的时候也会用到这两个方 ...

  2. 哈希表+哈希桶简介及实现

    最近在学习通信协议,链路层传输时,对于报文的识别处理,建立哈希识别规则:之前简单学习过哈希,还没深入过,闲来无事把学习的内容通俗的表达出来,也和大家分享一下,让新入门的童鞋很快理解. 1.哈希表 我们 ...

  3. MapSet哈希桶(基础+常用方法总结)

    作者:渴望力量的土狗 博客主页:渴望力量的土狗的博客主页 专栏:数据结构与算法 工欲善其事必先利其器,给大家介绍一款超牛的斩获大厂offer利器--牛客网 点击免费注册和我一起刷题吧 目录 1.map ...

  4. 高级数据结构与算法 | 哈希 :哈希冲突、负载因子、哈希函数、哈希表、哈希桶

    文章目录 哈希 哈希函数 常见的哈希函数 字符串哈希函数 哈希冲突 闭散列的解决方法 开散列的解决方法 负载因子以及增容 对于闭散列 对于开散列结构 具体实现 哈希表(闭散列) 插入 查找 删除 完整 ...

  5. 哈希表(闭散列、拉链法--哈希桶)

    哈希表,也称散列表,是一种通过key值来直接访问在内存中的存储的数据结构.它通过一个关键值的函数(被称为散列函数)将所需的数据映射到表中的位置来访问数据. 关于哈希表,主要为以下几个方面: 一.哈希表 ...

  6. (9)引入哈希桶的概念来实现一个哈希表

    前面的讲述了如何用链地址法实现一个哈希表,那么今天来分析一下另一种解决哈希冲突的做法,即为每个Hash值,建立一个Hash桶(Bucket),桶的容量是固定的,也就是只能处理固定次数的冲突,如1048 ...

  7. hash:哈希表 哈希桶

    目录 1.哈希的思想 2.解决冲突 3.哈希表(采用的闭散列,线性探测) 4.哈希桶(开散列) 5.总结 1.哈希的思想 hash是hash是一种根据存储的关键字的哈希值确定存储位置的算法.哈希值通过 ...

  8. 哈希结构(图文详解)【哈希表,哈希桶,位图,布隆过滤器】

    哈希结构 哈希概念 常见的K-V结构,实现了元素关键码与元素值的映射关系,但没有实现元素关键值与元素存储位置的映射关系,在遍历过程中,一般的顺序表或搜索二叉树要进行关键值的多次比较,其中顺序表的时间复 ...

  9. 14 哈希表和哈希桶

    文章目录 一.哈希表 二.哈希函数 2.1. 直接定址法(常用) 2.2. 除留余数法(常用) 2.3. 几种不常用的方法 三.哈希冲突 四.闭散列 4.1. 线性探测 4.2. 负载因子 4.3. ...

最新文章

  1. 「绩效领导力:聚焦战略目标有效落地」沙龙圆满落幕
  2. 必须掌握的Cookie知识点在这里
  3. 用java编程实现集合的交、并、差和补运算
  4. (三)Maven仓库介绍与本地仓库配置
  5. Problem G: C语言习题 医生值班
  6. django系列5.1--ORM对数据库的操作
  7. python画图遇到复数值数据时应该用numpy.abs()函数还是numpy.real()函数
  8. Java原始客户端操作Mongodb 增删改查
  9. 如何在 Mac 上安排电子邮件?
  10. Messenger Group Redesign - 缓解群组社交压力设计思考
  11. 闪耀光栅 (DMD) 的衍射效应
  12. 修复office安装提示1706
  13. R语言-两总体均值对比
  14. 如何正确在CSDN问答进行提问
  15. 服务器系统计划任务不执行,Windows 2008 r2任务计划程序执行批处理失败问题解决方法...
  16. linux应用层获取鼠标坐标
  17. 微信企业号开发,给用户推送信息
  18. 正在完成android更新三星,手机实时动态:这些都是三星手机正在获取Android 10
  19. 后端开发面试自我介绍_java开发面试评语
  20. 详细功能描述及代码带您快速接入百度大脑通用文字识别

热门文章

  1. swift 第四课 随意 设置button 图片和文字 位置
  2. JavaScript 图片上传预览效果
  3. 住宅的结构有哪些形式
  4. [Leedcode][JAVA][第837题][新21点][动态规划][数学]
  5. md5与des算法有何不同_到底AI芯片和传统芯片有何区别?
  6. java 窗口 单例_java单例模式实现面板切换
  7. python工厂模式 理解_浅谈Python设计模式 - 抽象工厂模式
  8. html文档php 取mac地址_cpu序列号_硬盘序列号,用vbs脚本获取网卡MAC,CPUID,硬盘序列号的实现代码...
  9. python正则表达式面试题_吐血总结!50道Python面试题集锦(4)
  10. MongoDB 操作范例