读数据结构与算法分析

哈希表

一种用于以常数平均时间执行插入、删除和查找操作的数据结构。

但是是无序的

一般想法

  • 通常为一个包含关键字的具有固定大小的数组
  • 每个关键字通过散列函数映射到数组中
  • 冲突:两个关键字映射到同一个值

散列函数

简单的散列函数

不均匀,不够好

typedef unsigned int Index ;

Index Hash(const char *key, int Tablesize)
{
unsigned int HashVal = 0; while(*key != '\0')
HashVal += *key++ ; return HashVal % Tablesize ;
}

一个好的散列函数

Index Hash(const char *key, int TableSize)
{
unsigned int HashVal = 0 ;
while(*key != '\0')
HashVal += (HashVal << 5) + *key++ ; return HashVal %TableSize ;
}

解决冲突

分离链接法


将散列到同一个值的所有元素保存在一个表中


类型声明

struct ListNode ;
typedef struct ListNode *Position ;
struct Hashbl ;
typedef struct HashTbl *HashTable ; HashTable IntializeTable(int TableSize) ;
void DestroyTable(HashTable H) ;
Position Find(ElemenetType Key, HashTable H) ;
Void Insert(ElementType Key, HashTable H) ;
ElementType Retireve(Position P) ; struct ListNode
{
ElementType Element ;
Position Next ;
} ; typedef Position List ; strcut HashTbl
{
int TableSize ;
List *TheLists ; //实则为指针数组
}

哈希表的初始化

HashTable IntializeTable(int TableSize)
{
HashTable H ; TableSize = NextPrime(TableSize) ;//将表的大小设为它下一个素数
H->TheList = malloc(sizeof (List) * H->TableSize) ;
if(H->TheList == NULL)
FatalError("内存不足") ;
for(int i = 0,i < H->TableSize; i++)
{
H->TheLists[i] = malloc(struct ListNode) ;
if(H->TheLists[i] == NULL)
FatalError("内存不足") ;
else
H->TheLists[i]->Next = NULL ;
} return H ;
}

Find函数

Position Find(ElementType Key, HashTable)
{
Position P ;
List L ;
L = H->TheLists[Hash(Key,H->TableSize)];
P = L->Next ;
while(P != NULL && P->Element != Key) //如果关键字为字符串,可能用到strcmp函数
P = P->Next ; return P ; }

Insert函数

void Insert(ElementType Key, HashTable H)
{
Position P ,TmpCell;
List L ;
TmpCell = malloc(ListNode) ;
if(TmpCell == NULL)
FatalError("内存不足") ;
else
{
L = H->TheLists[Hash(Key,H->TableSize)] ;
P = L->Next ;
TmpCell->Element = Key ;
TmpCell->Next = P ;
L->Next = TmpCell ;
free(TmpCell) ;
}
}

开放定址法

当发生冲突时,重新选择地址

Hi(X) = (Hash(X) + F(i)) mod TableSize ;
  • 线性探测法:会发生一次聚集
  • 平方探测法:效果较好
 F(i) = i^2

类型声明

typedef unsigned int Index ;
typedef Index Position ; struct Hashbl ;
typedef struct HashTbl *HashTable ; HashTable IntializeTable(int TableSize) ;
void DestroyTable(HashTable H) ;
Position Find(ElemenetType Key, HashTable H) ;
Void Insert(ElementType Key, HashTable H) ;
ElementType Retireve(Position P) ; enum KindOfEntry{Legitimate,Empty,Deleted} ; struct HashEntry
{
ElementType Element ;
enum KingOfEntry Info ;
} ; typedef struct HashEntry Cell ; strcut HashTbl
{
int TableSize ;
Cell *TheCells ; //直接用结构数组
}

Find函数

Position Find(ElementType Key,HashTable H)
{
Position P ;
int Num = 0;
P = H->TheCells[Hash(Key,H->TableSize)] ;
while(H->TheCells[P].Info != Empty && H->TheCells[P].Element != Key) //如果关键字为字符串需要使用strcmp函数
{
P += 2 * ++Num - 1 ;
if(P >= H->TableSize)
P -= H->TableSize ;
} return P ;
}

Insert函数

void Insert(ElementType Key, HashTable H)
{
Position P ;
P = Find(Key,H) ;
if(H->TheCells[P] != Legitimate)
{
H->TheCells[P].Info = Legitimate ;
H->TheCells[P].Element = Key ;//如果为字符串,则可能使用strcpy函数
}
}

总结

  • 哈希表以常数平均时间执行Insert和Find操作是重要特点,但它是无序的
  • 在解决冲突时使用不同的方法应该注意它的装填因子导致的效率问题
  • 应用:
    1. 编译器使用哈希表追踪代码中声明的变量
    2. 在图论当中每个节点应当由实际的名字
    3. 游戏编程中的变化表
    4. 在线拼写检验

哈希表 -数据结构(C语言实现)的更多相关文章

  1. [数据结构 - 第8章] 查找之哈希表(C语言实现)

    首先是需要定义一个哈希表的结构以及一些相关的常数.其中 HashTable 就是哈希表结构.结构当中的 elem 为一个动态数组. #define HASHSIZE 12 // 定义哈希表长为数组的长 ...

  2. 数据结构---哈希表的C语言实现(闭散列)

    原文地址:https://blog.csdn.net/weixin_40331034/article/details/79461705 构造一种存储结构,通过某种函数(hashFunc)使元素的存储位 ...

  3. 简单的哈希表实现 C语言

    简单的哈希表实现 简单的哈希表实现 原理 哈希表和节点数据结构的定义 初始化和释放哈希表 哈希散列算法 辅助函数strDup 哈希表的插入和修改 哈希表中查找 哈希表元素的移除 哈希表打印 测试一下 ...

  4. 哈希表的C语言实现

    首先介绍一下什么是哈希表.同线性表.树一样,哈希表也是一种数据结构,理想情况下可以不需要任何比较,一次存取便能得到所查记录.所以它的优点就是查找特定记录的速度快.因为哈希表是基于数组的,所以创建后就难 ...

  5. nginx 哈希表数据结构

    1.哈希表ngx_hash_t的优势和特点 哈希表是一种典型的以空间换取时间的数据结构,在没有冲突的情况下,对任意元素的插入.索引.删除的时间复杂度都是O(1).这样优秀的时间复杂度是通过将元素的ke ...

  6. C语言实现简单的哈希表

    这是一个简单的哈希表的实现,用c语言做的. 哈希表原理 这里不讲高深理论,只说直观感受.哈希表的目的就是为了根据数据的部分内容(关键字),直接计算出存放完整数据的内存地址. 试想一下,如果从链表中根据 ...

  7. 数据结构和算法(Golang实现)(26)查找算法-哈希表

    哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...

  8. 浅谈MatrixOne如何用Go语言设计与实现高性能哈希表

    目录 MatrixOne数据库是什么? 哈希表数据结构基础 哈希表基本设计与对性能的影响 碰撞处理 链地址法 开放寻址法 Max load factor Growth factor 空闲桶探测方法 一 ...

  9. C语言-简单哈希表(hash table)

    腾讯三面的时候,叫我写了个哈希表,当时紧张没写好···结果跪了··· 回来后粪发涂墙,赶紧写了一个! 什么都不说了···先让我到厕所里面哭一会··· %>_<% 果然现场发挥,以及基础扎实 ...

随机推荐

  1. ffmpeg 从mp4上提取H264的nalu

    转自http://blog.csdn.net/gavinr/article/details/7183499 1.获取数据 ffmpeg读取mp4中的H264数据,并不能直接得到NALU,文件中也没有储 ...

  2. MyBatis之Mapper XML 文件详解(四)-JDBC 类型和嵌套查询

    支持的 JDBC 类型为了未来的参考,MyBatis 通过包含的 jdbcType 枚举型,支持下面的 JDBC 类型. BITFLOATCHARTIMESTAMPOTHERUNDEFINEDTINY ...

  3. 【转载】RETE算法研究

    本文转自:http://www.ibm.com/developerworks/cn/opensource/os-drools/ RETE算法是大多数规则引擎采用的一种模式匹配算法,比如开源的Drool ...

  4. Web—06-JavaScript

    JavaScript介绍 JavaScript是运行在浏览器端的脚步语言,JavaScript主要解决的是前端与用户交互的问题,包括使用交互与数据交互. JavaScript是浏览器解释执行的,前端脚 ...

  5. iOS 获取蜂窝网络信号强度 包含iPhoneX XS XR XSMASX (最新)

    1.虽然各种直接获取信号强度的api都被封杀了.但是还有一个另类的黑魔法可以获取到.那就是遍历UIStatusBar了 网络上有的文章写的会崩溃 比如: - (int)getSignalStrengt ...

  6. Vue--- vue-cli 脚手架 安装 -reeber

    vue-cli 脚手架 安装   一. node安装 1)如果不确定自己是否安装了node,可以在命令行工具内执行: node -v  (检查一下 版本): 2)如果 执行结果显示: xx 不是内部命 ...

  7. mysql学习记录,CASE WHEN THEN ELSE END用法

    记mysql,case when then else end用法 用法1:搜索函数 SELECT r.order_no, r.golds, r.pay_tool, , ) ) END AS price ...

  8. Linux基础(03)、常用基础指令和操作

    目录 一.什么是Linux 二.常用基础指令 2.1.vi编辑 2.2.Linux文件类型 2.3.常用指令:增.删.改.查.其他 三.Linux的目录和权限 3.1.目录 3.2.权限 3.3.修改 ...

  9. Linq 综合写法

    var queryCount = (from pv in db.Province join pc in (from cc in         ((from v in db.ERPStockProdu ...

  10. header()函数用处

    header() 函数向客户端发送原始的 HTTP 报头. 认识到一点很重要,即必须在任何实际的输出被发送之前调用 header() 函数(在 PHP 4 以及更高的版本中,您可以使用输出缓存来解决此 ...