散列表及其查找
1. 散列的概念
散列表(hash table)是表示查找结构的一种有效方法。通过将关键码映射到表中某个位置来存储元素,然后根据关键码用同样的方式来直接访问。存储位置与关键码之间的对应函数关系 Address = hash(key) 。
2. 常见散列函数
- 直接定址法
- 除留余数法
- 数字分析法
- 平方取中法
- 折叠法
- 随机数法
3. 解决冲突的方法
通常关键码集合比散列表地址集合大得多。因此可能把不同关键码映射到同一个散列地址,这就产生了冲突(collision)。
3.1 开放定址法
3.1.1 线性探测法
3.1.2 平方探测法
3.1.3 双散列
3.2 分离链接法
代码示例:
//hashtable.h
typedef int typename;
typedef struct node{
typename elem;
sturct node* next;
}Node;
typedef Node* List;
typedef struct {
int tableSize;
List* theLists; //theLists为链表数组,因为List lst就是声明一个链表;好比int* p,p为整型数组
}HashTbl;
typedef HashTbl* HashTable //HashTable类型为指向该结构的指针类型
HashTable initTable(int tableSize);
List find(typename key, HashTable h);
void insert(typename key, HashTable h);
//hashtable.c
HashTable initTable(int tableSize){
HashTable h;
int i;
if(tableSize < minTableSize){
printf("tableSize too small\n");
return NULL;
}
//allocate table
h = malloc(sizeof(HashTbl));
if(h == NULL){
printf("out of space\n");
return NULL;
}
h->tableSize = nextPrime(tableSize);
//allocate array of lists
h->theLists = malloc(sizeof(List) * h->tableSize);
if(h->theLists == NULL){
printf("out of space\n");
return NULL;
}
//如果List的实现不用表头,到此为止,接下来为每个表分配一个表头
//并设next域为NULL
for(int i = 0; i < h->tableSize; ++i){
h->theLists[i] = malloc(sizeof(Node));
if(h->theLists[i] == NULL){
printf("out of space\n");
return;
}
else
h->theLists[i]->next = NULL;
}
return h;
}
List find(typename key, HashTable h){
List pNode;
List pHead;
pHead = h->theLists[Hash(key, h->tableSize)];
pNode = pHead->next;
while(pNode != NULL && pNode->elem != key)
pNode = pNode->next;
return pNode;
}
void insert(typename key, HashTable h){
List pNode, pNew, pHead;
pNode = find(key, h);
if(pNode == NULL){
pNew = malloc(sizeof(Node));
if(pNew == NULL){
printf("out of space\n");
return;
}
else{
pHead = h->theLists[Hash(key, h->tableSize)];
pNew->next = pHead->next;
pNew->elme = key;
pHead->next = pNew;
}
}
}
代码参考:数据结构与算法实现——C语言描述 (美)Mark Allen Weiss著 冯舜玺 译