您的位置:首页 > 编程语言

算法导论代码 第11章 散列表

2011-12-30 15:55 323 查看

第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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: