A simple hash table implementation
- A simple hash table implementation
- Principle
- Definitions of hash tables and node data structures
- Initializing and releasing a hash table
- Hash hashing algorithm
- Auxiliary function StrDup
- Inserting and modifying a hash table
- Find in hash table
- The removal of the hash TABLE element
- Hash table Printing
- Test it.
This is an implementation of a simple hash table, c
made in language.
Principle
Let's talk about the principle.
First there is an bucket
array, the so-called bucket.
A hash table is characterized by its presence in the 数据
table 相关性
, which is related, where the data should be computed.
This hash table is the data that is used to store some key-value pair ( key -- value
) relationships, which key
is its index in the table, and value
is the accompanying data.
By hashing the string key
into a bucket, the algorithm is deterministic, that is, one necessarily corresponds to the other key
bucket
.
Then there is the collision problem, which means that there are multiple key
corresponding index values. For example: There are three key
:, key1
the key3
key5
index value obtained by the hash algorithm is, that is keyToIndex
2
, these three key
produced a collision, for the collision processing, is to use linked list, and not to re-hash.
This is the header file that contains
#include <stdio.h>#include <stdlib.h>#include <string.h>#define BUCKETCOUNT 16
Definitions of hash tables and node data structures
struct hashEntry{ const char* key; char* value; struct hashEntry* next;};typedef struct hashEntry entry;struct hashTable{ entry bucket[BUCKETCOUNT]; //先默认定义16个桶};typedef struct hashTable table;
Initializing and releasing a hash table
//初始化哈希表void initHashTable(table* t){ int i; if (t == NULL)return; for (i = 0; i < BUCKETCOUNT; ++i) { t->bucket[i].key = NULL; t->bucket[i].value = NULL; t->bucket[i].next = NULL; }}//释放哈希表void freeHashTable(table* t){ int i; entry* e,*ep; if (t == NULL)return; for (i = 0; i<BUCKETCOUNT; ++i) { e = &(t->bucket[i]); while (e->next != NULL) { ep = e->next; e->next = ep->next; free(ep->key); free(ep->value); free(ep); } }}
Hash hashing algorithm
//哈希散列方法函数int keyToIndex(const char* key){ int index , len , i; if (key == NULL)return -1; len = strlen(key); index = (int)key[0]; for (i = 1; i<len; ++i) { index *= 1103515245 + (int)key[i]; } index >>= 27; index &= (BUCKETCOUNT - 1); return index;}
Auxiliary function StrDup
This is a more redundant approach because string.h
there are a number of such functions in the C standard library.
//在堆上分配足以保存str的内存//并拷贝str内容到新分配位置char* strDup(const char* str){ int len; char* ret; if (str == NULL)return NULL; len = strlen(str); ret = (char*)malloc(len + 1); if (ret != NULL) { memcpy(ret , str , len); ret[len] = ‘\0‘; } return ret;}
string.h
The related functions in
#include <string.h> char *strdup(const char *s); char *strndup(const char *s, size_t n); char *strdupa(const char *s); char *strndupa(const char *s, size_t n);
Inserting and modifying a hash table
This is the insertion and modification is a method, if it key
already exists in the hash table, then it is modified value
, otherwise it is to insert a node.
Insert data into the hash table int Insertentry (table* t, const char* key, const char* value) {int index, VLEN1, vlen2; entry* e, *ep; if (t = = NULL | | key = NULL | | value = NULL) {return-1; } index = Keytoindex (key); if (T->bucket[index].key = = NULL) {T->bucket[index].key = StrDup (key); T->bucket[index].value = StrDup (value); } else {e = EP = & (T->bucket[index]); while (E! = NULL) {/////strcmp (E->key, key) = = 0) {//Find key, replace value VL EN1 = strlen (value); Vlen2 = strlen (E->value); if (Vlen1 > Vlen2) {free (e->value); E->value = (char*) malloc (vlen1 + 1); } memcpy (E->value, value, Vlen1 + 1); return index; Insert completed} EP = e; E = e->next; }//End while (e ...//not found in current bucket//Create entry Join E = (entry*) malloc (sizeof (entry)); E->key = StrDup (key); E->value = StrDup (value); E->next = NULL; Ep->next = e; } return index;
Find in hash table
Because the hash table is saved 键值对
, this method looks for the corresponding one from the hash table key
value
. Note that the address returned here value
should not be modified for the data it points to, or it might happen unexpectedly.
//在哈希表中查找key对应的value//找到了返回value的地址,没找到返回NULLconst char* findValueByKey(const table* t , const char* key){ int index; const entry* e; if (t == NULL || key == NULL) { return NULL; } index = keyToIndex(key); e = &(t->bucket[index]); if (e->key == NULL) return NULL;//这个桶还没有元素 while (e != NULL) { if (0 == strcmp(key , e->key)) { return e->value; //找到了,返回值 } e = e->next; } return NULL;}
The removal of the hash TABLE element
This function is used to remove the corresponding node in the hash table key
, if it does not exist, then return NULL
. If it exists, it returns the address of the node. Note that this does not release the node, and if it is not needed, it should be released manually.
Finding the key corresponding to the entry//in the hash table finds the return entry and removes it from the hash table//not found return nullentry* removeentry (table* T, char* key) {int index; entry* E,*ep; When searching, use the EP as the return value if (t = = NULL | | key = = NULL) {return null; } index = Keytoindex (key); E = & (T->bucket[index]); while (E! = NULL) {if (0 = = strcmp (key, E->key)) {//If the bucket is the first if (E = = & (T->bucke T[index]) {//If the bucket has two or more elements//exchange First and second, then remove the second EP = e->next; if (ep = NULL) {entry TMP = *E;//Make a shallow copy exchange *e = *ep;//equivalent to the head node of the linked list has been removed *EP = tmp; This is the removed list header node Ep->next = NULL; } else {//This bucket is only the first element of EP = (entry*) malloc (sizeof (entry)); *ep = *e; E->key = E->value = NULL; E->next = NULL; }} else {//If it is not the first element of the bucket//Find its previous (this is the superfluous operation caused by poor design) EP = & (T->bucket[index]); while (ep->next! = e) EP = ep->next; Take e from it ep->next = e->next; E->next = NULL; EP = e; } return EP; }//End If (strcmp ... e = e->next; } return NULL;
Hash table Printing
This function is used to print the contents of a hash table.
void printTable(table* t){ int i; entry* e; if (t == NULL)return; for (i = 0; i<BUCKETCOUNT; ++i) { printf("\nbucket[%d]:\n" , i); e = &(t->bucket[i]); while (e->key != NULL) { printf("\t%s\t=\t%s\n" , e->key , e->value); if (e->next == NULL)break; e = e->next; } }}
Test it.
The data used for testing comes from native-related information.
int main () {table T; InitHashTable (&t); Insertentry (&t, "Computer model", "ASUS X550JK notebook computer"); Insertentry (&t, "Operating system", "Windows 8.1 64-bit (DirectX 11)"); Insertentry (&t, "Processor", "Intel Core I7-4710HQ @ 2.50GHz four core"); Insertentry (&t, "motherboard", "ASUS X550JK (Intel Haswell)"); Insertentry (&t, "Memory", "4 GB (Hynix/hyundai)"); Insertentry (&t, "Master HDD", "Hitachi HGST hts541010a9e680 (1 tb/5400 rpm)"); Insertentry (&t, "graphics card", "NVIDIA GeForce GTX 850M (2 GB/asus)"); Insertentry (&t, "display", "Chi Mei Cmn15c4 (15.3 inch)"); Insertentry (&t, "Optical drive", "Panasonic Dvd-ram uj8e2 S DVD burner"); Insertentry (&t, "sound card", "Conexant smartaudio HD @ Intel Lynx Point High Fidelity Audio"); Insertentry (&t, "network card", "Realtek rtl8168/8111/8112 Gigabit Ethernet Controller/asus"); Insertentry (&t, "motherboard model", "Asus X550JK"); Insertentry (&t, "chipset", "Intel Haswell"); Insertentry (&t, "BIOS", "x550jk.301"); Insertentry (&t, "date of manufacture", "06/26/2014"); Insertentry (&t, "Master", "Is Me"); Insertentry (&t, "price", "60-sheet Red Chairman"); Insertentry (&t, "main hard Disk", "Change a 120G Solid state"); entry* e = removeentry (&t, "motherboard model"); if (E! = NULL) {puts ("to be released after finding"); Free (E->key); Free (e->value); Free (e); e = NULL; } printtable (&t); Const char* keys[] = {"Display", "Master", "No", "processor"}; for (int i = 0; i < 4; ++i) {Const char* value = Findvaluebykey (&t, keys[i]); if (value = NULL) {printf ("Find%s\t=\t%s\n", keys[i], value); } else {printf ("Not Found%s\n", keys[i]); }} freehashtable (&t); GetChar (); return 0;}
Simple hash table for C language