一 简介
散列表(Hash table哈希表),根据关键码值(Key value)而直接进行访问的数据结构。
通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
这个映射函数叫做散列函数,存放记录的数组叫做散列表。
打个非常不严谨的比方:
NBA2K是一个广受篮球爱好者追捧的游戏。里面有每个NBA球员的战斗值,越高越厉害。
现在假设2K战斗值从1到100放在电脑中(不是全部每个战斗值都有,如可能没有10的值)
以战斗值为关键字,我想查找2K值为1的人是谁?按照传统的方法:
如果2K值无序存放在电脑中,要找1只能一个个取出来与1作比较,相等然后才能找到1存放那的人;
如果2k值有序存放在电脑中,可以通过比如折半查找比较等找到存1的位置然后找到人。
有没有不怎么耗时间,无须多次比较查找却一问就知道2K值为1的人是谁的方法呢?
答案是哈希表存储,以战斗值为关键字,给定战斗值就知道了存放的位置!!
但是哈希有时候会有冲突,也就是即便关键字不一样,可能通过哈希函数算出来的地址一样,这时候就尴尬了。
解决冲突的办法有很多,如链地址法(拉链法),建立一个公共溢出区等,本文主要是用到以下:
开放定址法:当冲突发生时,使用某种探查(亦称探测)技术在散列表中形成一个探查(测)序列。
Hi=(H(key) + di) MOD m,i=1,2,…,k(k<=m-1),其中H(key)为散列函数,m为散列表长,di为增量序列,可有下列三种取法:
1. di=1,2,3,…,m-1,称线性探测再散列;
2. di=1^2,-1^2,2^2,-2^2,⑶^2,…,±(k)^2,(k<=m/2)称二次探测再散列;
3. di=伪随机数序列,称伪随机探测再散列。
再散列法:即在同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生。
二 编程实现
准备测试文件:
有10条记录,第2行开始,每行两数,第一个数是2K值,第二个是关联的人。
比如第2行,对应着2K值6的人叫luxing富。
现在要做的事就是,知道了这些信息,然后用合适的位置存放在电脑中。
当下次一问2K值为6的人是谁时,电脑立即知道从哪儿个位置取相应的记录。
1.建立一个HashTable.h
#ifndef HASH.H
#define HASH.H
const int SUCCESS=1;//插入元素成功
const int UNSUCCESS=0;
const int EXIST=-1;//哈希表中有相同关键字元素,不再插入
const int MAX=3;
//hashsize数组存放哈希表需要重建时下一个容量大小
int hashsize[MAX]={11,19,37};
template
class HashTable{
private:
T *elem;
int count,length;//数据个数,哈希表容量
int sizeindex;//hashsize[sizeindex]为当前容量
int *random_d;//增量随机数数组指针
int Hash(KeyType key){
return key%length;
}
int Hash2(KeyType key){
return key%(length-1);//双散列函数探测法第二个哈希函数
}
void Random(){//随机探测法中建立伪随机数组
bool *a=new bool[length];
random_d=new int[length];
int i;
for(i=1;i>d_type;
switch(d_type){
case 0:cout<<"产生冲突时你选择使用线性探测法解决!"<
2.建立头文件func.cpp
struct DATA{
KeyType key;//关键字必有
string star;
};
void Visit(int i,DATA *c){
cout<<"["<key<<", "<star<<")"<>c.key>>c.star;
}
void InputKey(int &k){
cin>>k;
}
3.测试程序
#include
#include
#include
#include
#include
#include
using namespace std;
const int EMPTY=0;//尚未填充数据标志
const int REMOVE=-1;//数据删除标志
typedef int KeyType;//关键字类型
#include "func.cpp"
#include "HashTable.h"
int main()
{
HashTable h;
int i, j, n, p=0;
bool m;
DATA e;
KeyType k;
ifstream fin("test.txt");
fin>>n;
for(i=0; i>e.star;
j=h.InsertHash(e);
cout<
4.部分测试结果