散列(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)的更多相关文章

  1. 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)

    开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...

  2. 数据结构与算法分析——C语言描述 第三章的单链表

    数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...

  3. 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)

    #include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...

  4. C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载

    维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...

  5. 《数据结构与算法分析-Java语言描述》 分享下载

    书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...

  6. 读书笔记:《数据结构与算法分析Java语言描述》

    目录 第 3 章 表.栈和队列 3.2 表 ADT 3.2.1 表的简单数组实现 3.2.2 简单链表 3.3 Java Collections API 中的表 3.3.1 Collection 接口 ...

  7. 《数据结构与算法分析——C语言描述》ADT实现(NO.03) : 二叉搜索树/二叉查找树(Binary Search Tree)

    二叉搜索树(Binary Search Tree),又名二叉查找树.二叉排序树,是一种简单的二叉树.它的特点是每一个结点的左(右)子树各结点的元素一定小于(大于)该结点的元素.将该树用于查找时,由于二 ...

  8. 《数据结构与算法分析——C语言描述》ADT实现(NO.04) : AVL树(AVL-Tree)

    上次我们已经实现了普通的二叉查找树.利用二叉查找树,可以用O(logN)高度的树状结构存储和查找数据,提高了存储和查找的效率. 然而,考虑一种极端情形:依次插入1,2,3,4,5,6,7,8,9九个元 ...

  9. 《数据结构与算法分析——C语言描述》ADT实现(NO.01) : 栈(Stack)

    这次的数据结构是一种特殊的线性表:栈(Stack) 栈的特点是后入先出(LIFO),可见的只有栈顶的一个元素. 栈在程序中的地位非常重要,其中最重要的应用就是函数的调用.每次函数调用时都会创建该函数的 ...

随机推荐

  1. Impala系统架构

  2. DEV的GridControl控件的选中列属性设置高光

    设置Run Designer=>Views=> OptionsSelection下面的: EnableAppearanceFocusedCell = False,//鼠标移开,失去焦点,仍 ...

  3. 利用DNSQuery 进行DNS查询

    #include <WinSock2.h> #include <WinDNS.h> #pragma comment (lib, "Dnsapi.lib") ...

  4. adb命令 查看运行APP当前页面的Activity名称

    命令 adb shell "dumpsys window | grep mCurrentFocus" 结果

  5. [JZOJ3348] 【NOI2013模拟】秘密任务

    题目 题目大意 给你一个无向图,你要割掉一些边使得\(1\)到\(n\)的所有最短路径被阻截. 割掉一个边\((u,v)\)的代价为\(a_u\)或\(a_v\)(记为两种不同的方案). 问最小代价及 ...

  6. input、textarea等输入框输入中文时,拼音在输入框内会触发input事件的问题

    监听文本输入框的input事件,在拼写汉字(输入法)但汉字并未实际填充到文本框中(选词)时会触发input事件,如图: 但是在很多情况下,只需要输入到输入框的中文字符. 解决办法: 通过查阅资料得知在 ...

  7. CSS——背景渐变

    在线性渐变过程中,颜色沿着一条直线过渡:从左侧到右侧.从右侧到左侧.从顶部到底部.从底部到顶部或着沿任何任意轴.如果你曾使用过制作图件,比如说Photoshop,你对线性渐变并不会陌生. 兼容性问题很 ...

  8. 暴力贪心+预处理自动机——cf990E

    枚举每种灯管,然后找到代价最小的那种灯管 贪心策略:灯管从0开始向右放置,如果末尾是不能放置灯管的结点,那么要往回找到最近一个可以放置灯管的结点,在那里放置灯管 所以先预处理每个不能放置灯管的结点对应 ...

  9. AFO成功

    在dcoi一年多,还是发生了不少事情. 过程中也有些小遗憾,有做错的事情,有搞砸的事情,有没办法挽回的事情,这种没法读档的辣鸡游戏也是无可奈何的.对所有被我搞砸的事情说声对不起啦,至少在下一次的时候, ...

  10. 2015年MBA备考心得

    2015年12月份山大MBA备考心得 我在去年的12月26日参加了山大的MBA招生考试,在今年3月底参加了山大的复试,并被山大录取.初试英语70分,综合部分151,总分在今年的山大考生中是第16名:复 ...