《数据结构与算法分析——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),可见的只有栈顶的一个元素. 栈在程序中的地位非常重要,其中最重要的应用就是函数的调用.每次函数调用时都会创建该函数的 ...
随机推荐
- es5 JSON对象
1. JSON.stringify(obj/arr) js对象(数组)转换为json对象(数组) 2. JSON.parse(json) json对象(数组)转换为js对象(数组) <!DOCT ...
- 树莓派3b+ 实现视频监控
设备:树莓派3B+.Raspberry Pi Camera sudo raspi-config #启动camera sudo reboot #监测摄像头是否安装成功 raspistill -o ima ...
- 软件设计师_朴素模式匹配算法和KMP算法
1.从主字符串中匹配模式字符串(暴力匹配) 2. KMP算法
- duilib教程之duilib入门简明教程13.复杂控件介绍
首先将本节要介绍的控件全部拖到界面上,并调整好位置,如图: 然后将Name属性改成其他名字, 不能是[控件名+UI+数字]这种,因为这是DuiDesigner默认的名字,它不会实际写 ...
- Linux课程---16、apache虚拟主机设置(如何在一台服务器上配置三个域名)
Linux课程---16.apache虚拟主机设置(如何在一台服务器上配置三个域名) 一.总结 一句话总结:有三个网站www.lampym.com,bbs.lampym.com,mysql.lampy ...
- day18_文件处理_迭代器_生成器
#!/usr/bin/env python # -*- coding:utf-8 -*- # ********************day18_文件处理_迭代器_生成器 ************** ...
- Django的日常-模型层(1)
目录 Django的日常-模型层(1) 模型层 django测试环境 ORM查询 Django的日常-模型层(1) 模型层 模型层其实就是我们应用名下的models.py文件,我们在里面写入想要创建的 ...
- <每日一题>题目1:简单的注册和登录1.0
#版本1.0,最基本的注册登录'''1.注册,将账号和密码分别写在不同的文档里面2.登录,分别从账户文档和密码文档进行读取并登录''' #注册 Identity = input("请输入您想 ...
- git sync tags with remote
git 同步遠程標籤 在 .git/config的 [remote "origin"] 下加了 fetch = +refs/tags/*:refs/tags/* 最後就變成 [re ...
- 今天介绍一个渐变的方法,在shell里面自动生成注释简介
在编辑sh脚本时,我经常在shell中写一些注释.今天我介绍一种渐变方法,它可以在每次vim shell脚本时自动在shell中生成注释和其他信息. 让我们共享一个shell脚本模板文件,将其复制到用 ...