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

来源:互联网 发布:java工程师级别划分 编辑:程序博客网 时间:2024/05/22 06:43

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;#defineNIL((void*)-1)#defineDELETED ((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;}