《数据结构与算法分析——C语言描述》ADT实现(NO.05) : 散列(Hash)
散列(Hash)是一种以常数复杂度实现查找功能的数据结构。它将一个关键词Key,通过某种映射(哈希函数)转化成索引值直接定位到相应位置。
实现散列有两个关键,一是哈希函数的选择,二是冲突的处理。
对于哈希函数,例程中以“Key为int型,操作为取(关于表长的)模”为例。事实上,可以直接将其换成任何一个哈希函数,不会影响实现。
对于冲突处理,有两大类处理方案,一是分离链接法,二是开放定址法。开放定址法包括线性探测法、平方探测法、双散列法等,本文给出分离链接法和平方探测法的实现。
1. 分离链接法:
// HashSep.h #include <stdio.h>
#include <stdlib.h> struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef struct HashTbl *HashTable; typedef Position List; HashTable InitializeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
// HashSep.c #include "HashSep.h" struct ListNode
{
ElementType Key;
Position Next;
}; struct HashTbl
{
int TableSize;
List *TheLists;
}; int NextPrime(int N)
{
if (N % 2 == 0)
N++;
int i;
int NotPrime = 0;
for (;; N += 2)
{
NotPrime = 0;
for (i = 3; i * i <= N; i += 2)
if (N % i == 0)
{
NotPrime = 1;
break;
}
if (!NotPrime)
return N;
}
} int Hash(ElementType Key, int TableSize)
{
return Key * Key % 10;
} HashTable InitializeTable(int TableSize)
{
HashTable H;
int i;
if ((H = (HashTable)malloc(sizeof(struct HashTbl))) == NULL)
{
printf("Error! Out of memory! \n");
return NULL;
}
H->TableSize = NextPrime(TableSize);
H->TheLists = (Position *)malloc(H->TableSize * sizeof(Position));
for (i = 0; i < H->TableSize; i++)
{
if ((H->TheLists[i] = (List)malloc(sizeof(struct ListNode))) == NULL)
{
printf("Error! Out of memory! \n");
return NULL;
}
H->TheLists[i]->Next = NULL;
}
return H;
} void DestroyTable(HashTable H)
{
int i;
for (i = 0; i < H->TableSize; i++)
{
Position p, q;
q = H->TheLists[i];
p = q->Next;
while(p)
{
free(q);
q = p;
p = p->Next;
}
}
free(H);
} int Same(ElementType e1, ElementType e2)
{
return e1 == e2;
} Position Find(ElementType Key, HashTable H)
{
Position p;
p = H->TheLists[Hash(Key, H->TableSize)]->Next;
while(p)
{
if(Same(p->Key, Key))
break;
p = p->Next;
}
return p;
} void Insert(ElementType Key, HashTable H)
{
Position p;
List L;
if(Find(Key, H) != NULL)
return;
if((p = (Position)malloc(sizeof(struct ListNode))) == NULL)
{
printf("Error! Out of memory! \n");
return;
}
p->Key = Key;
L = H->TheLists[Hash(Key, H->TableSize)];
p->Next = L->Next;
L->Next = p;
}
2. 平方探测法
// HashQuad.h #include <stdio.h>
#include <stdlib.h> typedef unsigned int Index;
typedef Index Position; struct HashTbl;
typedef struct HashTbl *HashTable; typedef struct HashEntry Cell; HashTable InitializeTable(int TableSize);
void DestroyTable(HashTable H);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
ElementType Retrieve(Position P, HashTable H);
HashTable ReHash(HashTable H);
// HashQuad.c #include "HashQuad.h" enum KindOfEntry
{
Legitimate,
Empty,
Deleted
}; struct HashEntry
{
ElementType Element;
enum KindOfEntry Info;
}; struct HashTbl
{
int TableSize;
Cell *TheCells;
}; int NextPrime(int N)
{
if (N % 2 == 0)
N++;
int i;
int NotPrime = 0;
for (;; N += 2)
{
NotPrime = 0;
for (i = 3; i * i <= N; i += 2)
if (N % i == 0)
{
NotPrime = 1;
break;
}
if (!NotPrime)
return N;
}
} Index Hash(ElementType Key, int TableSize)
{
return Key % TableSize;
} HashTable InitializeTable(int TableSize)
{
HashTable H;
int i;
if ((H = (HashTable)malloc(sizeof(struct HashTbl))) == NULL)
{
printf("Error!\n");
return NULL;
}
H->TableSize = NextPrime(TableSize);
if ((H->TheCells = (Cell *)malloc(sizeof(Cell) * H->TableSize)) == NULL)
{
printf("Error!\n");
return NULL;
}
for (i = 0; i < H->TableSize; i++)
H->TheCells[i].Info = Empty;
return H;
} void DestroyTable(HashTable H)
{
free(H->TheCells);
free(H);
} Position Find(ElementType Key, HashTable H)
{
Index id = Hash(Key, H->TableSize);
int i = 0;
while (H->TheCells[id].Info == Legitimate && H->TheCells[id].Element != Key)
{
id += (++i << 1) - 1;
if (id >= H->TableSize)
id -= H->TableSize;
}
return id;
} void Insert(ElementType Key, HashTable H)
{
Position p = Find(Key, H);
if (H->TheCells[p].Info != Legitimate)
{
H->TheCells[p].Element = Key;
H->TheCells[p].Info = Legitimate;
}
} ElementType Retrieve(Position P, HashTable H)
{
return H->TheCells[P].Element;
} HashTable ReHash(HashTable H)
{
int i;
int OldSize;
Cell *OldCells;
OldCells = H->TheCells;
OldSize = H->TableSize;
H = InitializeTable(2 * OldSize);
for(i = 0; i < H->TableSize; i++)
if(OldCells[i].Info == Legitimate)
Insert(OldCells[i].Element, H);
free(OldCells);
return H;
}
《数据结构与算法分析——C语言描述》ADT实现(NO.05) : 散列(Hash)的更多相关文章
- 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)
开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...
- 数据结构与算法分析——C语言描述 第三章的单链表
数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...
- 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)
#include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...
- C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载
维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...
- 《数据结构与算法分析-Java语言描述》 分享下载
书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...
- 读书笔记:《数据结构与算法分析Java语言描述》
目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...
- 《数据结构与算法分析——C语言描述》ADT实现(NO.03) : 二叉搜索树/二叉查找树(Binary Search Tree)
二叉搜索树(Binary Search Tree),又名二叉查找树.二叉排序树,是一种简单的二叉树.它的特点是每一个结点的左(右)子树各结点的元素一定小于(大于)该结点的元素.将该树用于查找时,由于二 ...
- 《数据结构与算法分析——C语言描述》ADT实现(NO.04) : AVL树(AVL-Tree)
上次我们已经实现了普通的二叉查找树.利用二叉查找树,可以用O(logN)高度的树状结构存储和查找数据,提高了存储和查找的效率. 然而,考虑一种极端情形:依次插入1,2,3,4,5,6,7,8,9九个元 ...
- 《数据结构与算法分析——C语言描述》ADT实现(NO.01) : 栈(Stack)
这次的数据结构是一种特殊的线性表:栈(Stack) 栈的特点是后入先出(LIFO),可见的只有栈顶的一个元素. 栈在程序中的地位非常重要,其中最重要的应用就是函数的调用.每次函数调用时都会创建该函数的 ...
随机推荐
- 【笔记篇】斜率优化dp(四) ZJOI2007仓库建设
传送门戳这里>>> \(n\leq1e6\), 显然还是\(O(n)\)的做法. 这个题有个条件是只能运往编号更大的工厂的仓库, 这也是写出朴素dp的方程的条件. 我们令\(f[i] ...
- yii2 返回json和文件下载
JSON 調用的控制器返回 json格式的數據即可,對json裡面的數據沒有要求 如在控制器中添加一個方法: public function actionRemoveImage($id){ Yii:: ...
- 2019.12.04 Java中的内存分配
Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识.一般 ...
- 【JZOJ6360】最大菱形和(rhombus)
description analysis 容易想到把原矩阵翻转\(45°\),然后每个数再用\(0\)隔开 然后就变成了求最大子正方形,求完二维前缀和之后就很好做了 code #pragma GCC ...
- Photoshop基本操作
PS 工具是我们使用频率比较高的软件之一, 我们学习PS目的不是为了设计海报做电商和UI的,而是要求: 会简单的抠图 会简单的修改PSD效果图 熟练的切图 能和网站美工美眉有共同话题..... Pho ...
- thinkphp 模版引擎
系统支持原生的PHP模板,而且本身内置了一个基于XML的高效的编译型模板引擎,系统默认使用的模板引擎是内置模板引擎,关于这个模板引擎的标签详细使用可以参考模版引擎部分. 内置的大理石平台检定规程模板引 ...
- 0924CSP-S模拟测试赛后总结
50分-rank28 我是第二机房垫底大垃圾. 赛时T1和T2其实想到了正解??安慰自己罢了. 真正的CSP-S的赛后你还能和主办方争论说自己其实想到了正解要求人家硬给你个省一不成?? 出题人不知道到 ...
- js 异步编程思想
一.js中的异步编程有四种情况 1.定时器 2.所有的事件绑定 3.ajax异步请求 4.回调函数
- ASP.NET的底层体系1
文章引导 1.ASP.NET的底层体系1 2.ASP.NET的底层体系2 引言: 学习ASP.NET,要想做的更好,不了解ASP.NET是不行的.一个有理想的程序员都会像挤压海绵一样,努力的去学习和获 ...
- 使用JDK自带功能,实现一个简单的Web Service接口发布
万事开头难,本篇文章的目的就是使用JDK自带的功能,实现一个最简单的Web Service接口的发布. 下图是项目的组成,主要有三个部分,一个接口(WS),一个接口的实现类(WSImp),还有一个接口 ...