哈希表
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
哈希表可以存储各种类型的数据,当我们从哈希表中查找所需要的数据时,理想情况是不经过任何比较,一次存取便能得到所查记录,那就必须在记录的存储位置和它的关键字之间建立一个确定的对应关系 f,使每个关键字和结构中一个唯一的存储位置相对应。(关键字就是所要存储的数据,存储位置相当于数组的索引)
试设想,若在记录的关键字和其存储位置之间建立一个确定的函数关系f,即关键字为key的记录存储在f(key)的位置上,则对于给定值kval若存在关键值等于kval的记录,则一定在f(kval)的位置上。通常的做法是:
1)设定一个一维数组的空间来存放各个记录,发f(key)就是数组的下标。
看一个例子:假设有一个含80个记录的查找表,记录的关键字均为两位10进制的数。则设存储这组记录的一维数组为:
hastable[100]
并且令关键字为key的记录存储在hashtable数组中第i个分量中hashtable[i]:
key = f(key)=i //那么假设查找表中89,就存储89=hashtable[89]中.
可以看出(1)存储记录的一维数组hashtable被称为哈希表,函数f称为哈希函数。在关键字和记录位置之间设定了一个确定的关系f,则在哈希表中查找关键字kval等于给定值的记录时,仅需直接对给定值进行某种运算,求得记录的存储位置f(kval),不需要和其他关键字的记录进行比较。
(2)一般情况下,所设哈希表的空间比记录的集合较大,此时虽然浪费了空间,但提高了查找效率。假设哈希表的空间大小为M,在表中填入的记录数为n,定义装填系数α:
α=n/m;实际应用时0.65<α<0.85;
构造函数的几种方法:
1)除留余数法
2)平方取中法
3)折叠法
处理冲突的方法
1)开放地址法
2)链地址法
j
例子
假设 关键字是前10个完全平方数并设散列函数(Hash(X) = X mod 10)
题目来源:https://leetcode-cn.com/problems/two-sum/
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍
//哈希表的结构是一个链表数组;在初始化时分配空间Hashmap是指向该结构体的指针;
typedef struct{
long val;
int subscript;
struct node *next;
}Node,*LinkList//创建链表的节点;
typedef struct{
LinkList *TheList;
}HashTbl;//TheList是一个数组,数组的值时Node的指针;
typedef HashTbl *Hashmap;//哈希表
void Init(Hashmap * hashTble,int n)
{
(*hashTble) = (Hashmap)malloc(sizeof(HashTbl));//给散列的结构分配空间
(*hashTble)->TheList = (LinkList*)malloc(sizeof(LinkList)*n);//指针数组
int i;
for( i=0;i<n;i++)
{
(*hashTble)->TheList[i]=(LinkList)calloc(1,sizeof(Node));
}
}
void insert(Hashmap hashTble,long val,int subscript,int n)
{
int t = abs(val)%n;
LinkList temp = hashTble->TheList[t];
LinkList add = (LinkList)malloc(sizeof(Node));
add->val = val;
add->subscript = substript;
add->next = temp->next;
temp->next = add;
}
int search(Hashmap hashTble,long target,int n)
{
int index = abs(target)%n;
struct node *temp = hashTble->TheList[index]->next;
while(temp)
{
if(temp->val==target)
{
return temp->subscript;
}
temp = temp->next;
}
return -1;
}
void freeHashTble(Hashmap hashTble,int n)
{
int i=0;
struct node *temp = NULL,*delete = NULL;
for(i = 0;i<n;i++)
{
temp = hashTable->TheList[i];
delete = temp;
while(temp)
{
delete = temp;
temp = temp->next;
free(delete)
}
}
free(hashTble);
}
int *twoSum(int *nums,int numSize,int target,int *returnSize)
{
int i=0,j=0;
int n=numSize,index=0;
int* result=NULL;
*returnSize=0;
Hashmap hashTble;
Init(&hashTble,n);
for(i=0;i<n;i++)
{
index = search(hashTble,target-num[i],n);
if(-1==index)
insert(hashTble,nums[i],i,n);
else
{
result = (int*)malloc(sizeof(int)*2);
result[0] = index;
result[1]= i;
*returnSize = 2;
freeHashTble(hashTble,n)
return result;
}
}
freeHashTable(hashTable, n); return result;
}