c哈希表hashtable操作
#ifndef HASH_TABLE_H #define HASH_TABLE_H #include "linkedlist.h" typedef struct { int capacity; LinkedList **elements; int seed; } HashTable; HashTable *hash_table_construct(int size); HashTable *hash_table_clone(HashTable *table); void has_table_destroy_clone(HashTable *table); void hash_table_destroy(HashTable *table); void hash_table_add_element(HashTable *table, const void *data, int hash_code); const void *hash_table_get_element(HashTable *table, int hash_code); void hash_table_remove_element(HashTable *table, int hash_code); int hash_table_get_index(HashTable *table, int hash_code); int hash_table_get_hash_code_from_string(const char *string); #endif
-------------------------------------------
#include "hashtable.h" #include "linkedlist.h" #include "logger.h" #include <stdlib.h> #include <stdio.h> #ifdef DMALLOC #include "dmalloc.h" #endif typedef struct { int hash_code; const void *data; } HashTableElement; static HashTableElement *hash_table_element_construct(int hash_code, const void *data); static void hash_table_element_destroy(HashTableElement *element); /* * FIXME: Needs to handle growing past initial capacity when table gets full. * Note that it will be a slow operation because all table elements * will have to be rehashed. * * FIXME: Currently uses chaining which isn't great. Probably would be better * to do double hashing or quadratic probing or something. If not, * it would be at least a good idea to maintain which elements get * accessed the most in any given chain and move them to the front. */ HashTable *hash_table_construct(int size) { HashTable *table = NULL; /* * Allocate space for the object and set all fields to zero. */ table = calloc(1, sizeof(HashTable)); if (table == NULL) { return NULL; } /* * Allocate space for the table elements */ table->elements = calloc(size, sizeof(LinkedList *)); if (table->elements == NULL) { return NULL; } /* * Initially set the capacity to the passed size */ table->capacity = size; /* * FIXME: Do something with this. Make it a random number or something. */ table->seed = 1; /* * Return the HashTable object */ return table; } void hash_table_destroy(HashTable *table) { int i = 0; if (table == NULL) { return; } /* * Free all the chains */ if (table->elements != NULL) { for (i = 0; i < table->capacity; i++) { if (table->elements[i] != NULL) { linked_list_destroy(table->elements[i]); table->elements[i] = NULL; } } free(table->elements); table->elements = NULL; } free(table); } HashTable *hash_table_clone(HashTable *table) { /* * Fixme, write this function! */ return table; } void has_table_destroy_clone(HashTable *table) { /* * Fixme, write this function! */ } void hash_table_add_element(HashTable *table, const void *data, int hash_code) { LinkedListNode *node = NULL; HashTableElement *element = NULL; int index = -1; if (table == NULL) { return; } /* * Find out which chain the element should be appended to. */ index = hash_table_get_index(table, hash_code); if (index == -1) { return; } /* * If there isn't a LinkedList object at the index * already then put one there */ if (table->elements[index] == NULL) { table->elements[index] = linked_list_construct(); if (table->elements[index] == NULL) { return; } } /* * Create a HashTableElement object to hold the given data and hash code */ element = hash_table_element_construct(hash_code, data); /* * If the element could not be created then bail */ if (element == NULL) { return; } /* * Create a linked list node with the given element */ node = linked_list_node_construct(element); if (node == NULL) { return; } /* * Otherwise, add the node to the linked list */ linked_list_append_node(table->elements[index], node); } const void *hash_table_get_element(HashTable *table, int hash_code) { LinkedListNode *node = NULL; HashTableElement *element = NULL; const void *data = NULL; int index = -1; if (table == NULL) { return NULL; } /* * Which chain does the desired element reside on? */ index = hash_table_get_index(table, hash_code); if (index == -1) { return NULL; } if (table->elements[index] == NULL) { return NULL; } /* * Start at the beginning of the chain. */ linked_list_seek_start(table->elements[index]); /* * Traverse each node, and compare hash codes for a valid match */ while((node = linked_list_get_next_node(table->elements[index])) != NULL) { element = (HashTableElement *) linked_list_node_get_data(node); if (hash_code == element->hash_code) { data = element->data; break; } } if (data == NULL) { } return data; } int hash_table_get_index(HashTable *table, int hash_code) { if (table == NULL) { return -1; } if (hash_code < 0) { return -1; } if (table->capacity == 0) { return -1; } /* * Is their a better hashing function? */ return (table->seed * hash_code) % table->capacity; } int hash_table_get_hash_code_from_string(const char *string) { const char *p = NULL; int hash_code = -1, i = 0; if (string == NULL) { return -1; } /* * Generate a reversed (least significant character is most significant * number) radix 128 evaluated polynomial of the input key */ for (p = string; p[0] != 0; p++, i++) { int j = 0, coeff = 1; for (j = 0; j < i; j++) { coeff += 128; } hash_code += (p[0] * coeff); } return hash_code; } static HashTableElement *hash_table_element_construct(int hash_code, const void *data) { HashTableElement *element = NULL; /* * Allocate space for the object and set all fields to zero. */ element = calloc(1, sizeof(HashTableElement)); if (element == NULL) { return NULL; } element->hash_code = hash_code; element->data = data; return element; } static void hash_table_element_destroy(HashTableElement *element) { if (element == NULL) { return; } free(element); }
虽功未成,亦未敢藏私,众侠诸神通尽录于此,竟成一笈,名葵花宝典,以飨后世。
邮箱:steven9801@163.com
QQ: 48039387
邮箱:steven9801@163.com
QQ: 48039387