第11章 散列表
11.2 散列表
#include <stdio.h>
#include <stdlib.h>
/*通过链接法解决碰撞*/
typedef struct hash_chain_type *hash;
typedef struct list_type *list;
struct list_node {
void *key;
struct list_node *prev;
struct list_node *next;
};
struct list_type {
struct list_node *head;
};
struct hash_chain_type {
list *list_array;
int (*get_value) (const void *);
int num;
};
void list_node_ini(struct list_node *p, void *key)
{
p->key = key;
p->prev = NULL;
p->next = NULL;
}
list list_create()
{
list l = malloc(sizeof(struct list_type *));
l->head = NULL;
return l;
}
void list_destroy(list l, void (*free_key) (void *))
{
struct list_node *x = l->head;
while (x != NULL) {
struct list_node *del = x;
x = x->next;
free_key(del->key);
free(del);
}
free(l);
}
struct list_node *list_search(list l, void *k,
int (*comp) (const void *, const void *))
{
struct list_node *x = l->head;
while (x != NULL && comp(x->key, k) != 0) {
x = x->next;
}
return x;
}
void list_insert(list l, struct list_node *x)
{
x->next = l->head;
if (l->head != NULL) {
l->head->prev = x;
}
l->head = x;
x->prev = NULL;
}
void list_delete(list l, struct list_node *x)
{
if (x->prev != NULL) {
x->prev->next = x->next;
} else {
l->head = x->next;
}
if (x->next != NULL) {
x->next->prev = x->prev;
}
}
hash hash_create(int num, int (*get_value) (const void *))
{
hash h = malloc(sizeof(struct hash_chain_type));
h->num = num;
h->get_value = get_value;
h->list_array = malloc(sizeof(list) * num);
for (int i = 0; i < num; i++) {
h->list_array[i] = list_create();
}
return h;
}
void hash_destroy(hash h, void (*free_key) (void *))
{
for (int i = 0; i < h->num; i++) {
list_destroy(h->list_array[i], free_key);
};
free(h->list_array);
free(h);
}
int hash_value(hash h, int key)
{
return key % h->num;
}
void hash_insert(hash h, struct list_node *x)
{
int key = h->get_value(x);
list l = h->list_array[hash_value(h, key)];
list_insert(l, x);
}
struct list_node *hash_search(hash h, int key,
int (*comp) (const void *, const void *))
{
list l = h->list_array[hash_value(h, key)];
return list_search(l, &key, comp);
}
void hash_delete(hash h, struct list_node *x)
{
if (x == NULL)
return;
int key = h->get_value(x);
list l = h->list_array[hash_value(h, key)];
list_delete(l, x);
}
/*用于list_node的key成员的比较函数*/
int cmp_int(const void *p1, const void *p2)
{
const int *pa = p1;
const int *pb = p2;
if (*pa < *pb)
return -1;
if (*pa == *pb)
return 0;
return 1;
}
/*从list_node类型指针中取得关键字的整数值*/
int get_value(const void *x)
{
const struct list_node *p = x;
const int *ip = p->key;
return *ip;
}
int main()
{
hash h = hash_create(10,get_value);
for (int i = 0; i < 10; i++) {
struct list_node *x = malloc(sizeof(struct list_node));
int *p = malloc(sizeof(int));
*p = i;
list_node_ini(x, p);
printf("%d ", *p);
hash_insert(h, x);
}
printf("\n");
int k = 0;
struct list_node *x = hash_search(h, k, cmp_int);
printf("查找关键字:%d的结果:%s\n", k,
x != NULL ? "成功" : "失败");
if (x != NULL) {
hash_delete(h, x);
free(x->key);
free(x);
x = hash_search(h, k, cmp_int);
printf("删除关键字:%d的结果:%s\n", k,
x == NULL ? "成功" : "失败");
}
hash_destroy(h, free);
return 0;
}
11.4 开放地址法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct hash_open_addressing_type *hash;
#define NIL ((void*)-1)
#define DELETED ((void*)-2)
struct hash_open_addressing_type {
void **array;
int num;
int (*hash_fun) (hash, int, int);
int (*get_value) (const void *);
};
hash hash_create(int num, int (*hash_fun) (hash, int, int),
int (*get_value) (const void *))
{
hash h = malloc(sizeof(struct hash_open_addressing_type));
h->num = num;
h->array = malloc(sizeof(void *) * num);
for (int i = 0; i < h->num; i++)
h->array[i] = NIL;
h->hash_fun = hash_fun;
h->get_value = get_value;
return h;
}
void hash_destroy(hash h, void (*free_key) (void *))
{
for (int i = 0; i < h->num; i++) {
if (h->array[i] != NIL && h->array[i] != DELETED) {
free_key(h->array[i]);
}
}
free(h->array);
free(h);
}
int hash_insert(hash h, void *p)
{
int key = h->get_value(p);
int i = 0;
int j = 0;
do {
j = h->hash_fun(h, key, i);
if (h->array[j] == NIL || h->array[j] == DELETED) {
h->array[j] = p;
return j;
} else {
i++;
}
} while (i < h->num);
return -1;
}
/*返回槽的索引*/
int hash_search(hash h, int key)
{
int i = 0;
int j = 0;
do {
j = (h->hash_fun) (h, key, i);
if (h->array[j] != DELETED) {
int value = h->get_value(h->array[j]);
if (value == key) {
return j;
}
}
++i;
} while (h->array[j] != NIL && i < h->num);
return -1;
}
/*返回槽的索引*/
int hash_delete(hash h, int key)
{
int i = hash_search(h, key);
if (i != -1) {
h->array[i] = DELETED;
}
return i;
}
int hash_fun_linear(hash h, int key, int i)
{
int h1 = key % h->num;
return (h1 + i) % h->num;
}
int hash_fun_quadratic(hash h, int key, int i)
{
int h1 = key % h->num;
return (h1 + i + i * i) % h->num;
}
int hash_fun_double_hash(hash h, int key, int i)
{
int h1 = key % h->num;
int h2 = key % h->num + 1;
return (h1 + i * h2) % h->num;
}
/*从存到hash表里的类型指针中取得关键字的整数值*/
int get_value(const void *x)
{
const int *ip = x;
return *ip;
}
int main()
{
hash h = hash_create(10, hash_fun_double_hash, get_value);
for (int i = 0; i < 10; i++) {
int *p = malloc(sizeof(int));
*p = i;
printf("%d ", *p);
hash_insert(h, p);
}
printf("\n");
int k = 0;
int pos = hash_search(h, k);
printf("查找关键字:%d的结果:%s\n", k,
pos != -1 ? "成功" : "失败");
int *p = h->array[pos];
int delete_key = get_value(p);
hash_delete(h, delete_key);
free(p);
pos = hash_search(h, k);
printf("删除关键字:%d的结果:%s\n", k,
pos == -1 ? "成功" : "失败");
hash_destroy(h, free);
return 0;
}