1.HashTable
散列表:可根据关键字直接访问的数据结构。关键字与存储地址存在映射关系。(以存储空间换查找时间,空间换时间数据结构)
2.关键字与存储地址的映射关系
通过散列函数将关键字映射指定地址。
设计散列函数:
1.直接定址:hash(key) = a*key+b 2.除留余数法:hash(key) = key%p(简单常用)
3.数字分析法 4.平方取中法 5.折叠法
3.散列地址冲突
不同key映射相同散列会造成地址冲突,解决地址冲突的两种方法:
1.开放地址:将地址冲突的key存储到空闲的散列表中(Haddress=(hash(key)+d)%p,p为表长)
d为造成地址冲突后下一地址地增量
(1)d随冲突次数增加而增加,称线性探测法
(2)d随随冲突次数以平方增长,称平方探测法
(3)d取对key再散列hash2*冲突次数,称再散列法或双散列法
(4)d取伪随机序列(指有某种随机特性的序列,序列元素间有确定关系存在),称伪随机序列法
2.链接法:
用链表存储同地址冲突关键字,每一散列地址对应一链表。(有利于多元素的插入和删除情况)
4.C实现(散列函数采取除留余数法,地址冲突采取链接法解决)
#include <stdio.h>
#include <malloc.h>
#define OK 1
#define ERROR -1
#define CAPACITY 10
#define ElemType int
#define Status int
typedef struct _Node {
ElemType value;
_Node* next;
}Node;
typedef struct _HashTable {
Node elems[CAPACITY];
int count;
int capacity;
}HashTable;
Status InitHashTable(HashTable* ht);
Status InsertNode(HashTable* ht, ElemType elem);
Status Search(HashTable* ht, ElemType elem);
Node* new_Node();
int hash(int key); //计算key 对应地址, 求余取址
Status addLinkNode(Node* list, ElemType elem);
void print_table(HashTable* ht) {
Node* head;
for (int i = 0; i < CAPACITY; i++) {
head = &ht->elems[i];
printf("elem[%d].head->:", i);
while (head->next) {
head = head->next;
printf(" %d ->", head->value);
}
printf("\n");
}
}
int main() {
int key[18] = { 1,2,4,55,11,44,22,33,77,4,5,10,8,9,666,12,14,15};
HashTable ht;
InitHashTable(&ht);
for (int i = 0; i < 18; i++) InsertNode(&ht, key[i]);
print_table(&ht);
int n; scanf("%d", &n);
return 0;
}
Status InitHashTable(HashTable* ht) {
for (int i = 0; i < CAPACITY; i++) {
ht->elems[i] = *new_Node();
ht->elems[i].value = -1;
ht->elems[i].next = NULL;
}
ht->capacity = CAPACITY;
return OK;
}
int hash(int key) {
return key % CAPACITY;
}
Status InsertNode(HashTable* ht, ElemType elem) {
int hash_address = hash(elem);
int status = addLinkNode(&ht->elems[hash_address],elem); //指定hashaddress的单链表添加元素
if (status == OK) {
ht->count++;
return OK;
}
return ERROR;
}
Status Search(HashTable* ht, ElemType elem) {
return 0;
}
Node* new_Node() {
return (Node*)malloc(sizeof(Node));
}
Status addLinkNode(Node* list, ElemType elem) {
Node* head = list;
while (head->next) {
head = head->next;
}
Node* newnode = new_Node();
newnode->value = elem;
newnode->next = NULL;
head->next = newnode;
return OK;
}