《数据结构与算法分析——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),可见的只有栈顶的一个元素. 栈在程序中的地位非常重要,其中最重要的应用就是函数的调用.每次函数调用时都会创建该函数的 ...
随机推荐
- javascript小技巧-js小技巧收集(转)
本文转载自:http://blog.csdn.net/ocean20/article/details/2498699 每一项都是js中的小技巧,但十分的实用! 1.document.write(&qu ...
- VS环境下,DEV插件的ComboBoxEdit控件最简单的数据源绑定和获取方法
使用 ComboBoxEdit 控件绑定key/value值: 因为 ComboBoxEdit 没有 DataSource 属性,所以不能直接绑定数据源,只能一项一项的添加. 首先创建一个类ListI ...
- artTemplate(mark)
一个渲染性能出众模板引擎,无论在 NodeJS 还是在浏览器中都可以运行. 特性 拥有接近 JavaScript 渲染极限的的性能 调试友好:语法.运行时错误日志精确到模板所在行:支持在模板文件上打断 ...
- python open函数关于w+ r+ 读写操作的理解(转)
r 只能读 (带r的文件必须先存在)r+ 可读可写 不会创建不存在的文件.如果直接写文件,则从顶部开始写,覆盖之前此位置的内容,如果先读后写,则会在文件最后追加内容.w+ 可读可写 如果文件存在 则覆 ...
- Algo: Majority Element
Approach #1 Brute Force Intuition We can exhaust the search space in quadratic time by checking w ...
- Android开发 ImageView开发记录
改变图片的着色 默认是这个方法 /** * 为图像设置着色选项. Assumes * {@link PorterDuff.Mode#SRC_ATOP} blending mode. * * @para ...
- Erlang学习记录:语法和特性
特性 大下排序:number < atom < reference < fun < port < pid < tuple < list < bit st ...
- chrome的驱动安装
首先找到对应的chromedriver,百度搜索,http://npm.taobao.org/mirrors/chromedriver/ 将下载好的chrome驱动解压,放在/usr/loacl/bi ...
- hdu多校第二场1011 (hdu6601) Keen On Everything But Triangle 主席树
题意: 给定一个数列,每次询问一个区间,问这个区间中的值可组成的周长最大的三角形的周长. 题解: 定理1:给定一些值,这些值中组成边长最大的三角形的三条边的大小排名一定是连续的. 证明:假如第k大,第 ...
- Java-Maven-pom.xml-project-repositories:repositories
ylbtech-Java-Maven-pom.xml-project-repositories:repositories <!--发现依赖和扩展的远程仓库列表. --> 1. platfo ...