哈希表

来源:互联网 发布:淘宝仓管 编辑:程序博客网 时间:2024/05/22 12:04

哈希表的结构是这样的


//HashTable.h

#ifndef _HASHTABLE_H_#define _HASHTABLE_H_#include <stdlib.h>#include <stdbool.h>#define BUCKET_SIZE5//基桶与溢出桶大小,此处的值表示可容纳5个元素#define HASHTABLE_SIZE17//哈希表中基桶个数,为了使得出的哈希因子在所有可得的值中得出任一值的概率相同,所以使用素数作为基桶个数#define INVALID_VALUE-11111//无效标记typedef int EleType;typedef int KeyType;struct _ElementNode_//元素节点类型,键值对{KeyType Key;EleType Val;};//存储键值对,Hash与之前的平衡二叉树都应该是键值对,如果只有值,查找函数返回值的地址,如果使用地址修改了值,会发生令人不愉快的事情。typedef struct _HashBucket_{_ElementNode_ Data[BUCKET_SIZE];   struct _HashBucket_ *Bucket;//解决冲突的方式是链地址法}HashBucket;//桶节点类型typedef HashBucket* HashTable;bool HashTableInit(HashTable *Hash);//初始化哈希表bool HashTableInsert(HashTable Hash, KeyType Key, EleType Data);//插入键值对EleType *HashTableFind(HashTable Hash, KeyType Key);//根据键查找值bool HashTableDelete(HashTable Hash, KeyType Key);//删除键值对void HashTableDestroy(HashTable *Hash);//摧毁哈希表#endif //_HASHTABLE_H_



//HashTable.c

#include "HashTable.h"static int HashFunc(KeyType Key){return Key % HASHTABLE_SIZE;//除留取余法}static _ElementNode_ *HashTableFind_(HashTable Hash, KeyType Key){int pos = 0, i = 0;HashBucket *p = NULL;if( NULL == Hash )return NULL;pos = HashFunc(Key);//求Key所对应的基桶p = Hash + pos;//指向该基桶for (i = 0; i < BUCKET_SIZE; ++i)//在基桶内寻找位置{if( Key == p->Data[i].Key )return p->Data + i;//返回找到的位置}//不在基桶中while (NULL != p->Bucket)//到溢出桶中查找{p = p->Bucket;for (i = 0; i < BUCKET_SIZE; ++i){if( Key == p->Data[i].Key )return p->Data + i;}}//也不在溢出桶中return NULL;}//更新一个桶内的元素,如果是以存在元素则用新值更新,如果是不存在元素则找空位置插入static bool UpdataBucket(HashBucket *p, KeyType Key, EleType Data){int i = 0;for (i = 0; i < BUCKET_SIZE; ++i)//遍历该基桶中的每个位置,查找是否有空位,或者是否可以更新现有元素{if (Key == p->Data[i].Key)//Key已存在则更新Val,相当于是对已存在元素进行修改{p->Data[i].Val = Data;return true;}if (INVALID_VALUE == p->Data[i].Key)//Key不存在则增加元素记录,即将新元素存入哈希表{p->Data[i].Key = Key;p->Data[i].Val = Data;return true;}}return false;}//创建一张含有HASHTABLE_SIZE个基桶的哈希表bool HashTableInit(HashTable *Hash){int i = 0, j = 0;HashBucket * p = (HashBucket *)malloc(sizeof(HashBucket) * HASHTABLE_SIZE);if( NULL == p ){*Hash = NULL;return false;}for (i = 0; i < HASHTABLE_SIZE; ++i)//初始化全部基桶{for (j = 0; j < BUCKET_SIZE; ++j)//初始化桶内每个位置{p[i].Data[j].Key = INVALID_VALUE;p[i].Data[j].Val = INVALID_VALUE;}p[i].Bucket = NULL;}*Hash = p;return true;}//插入操作函数,当Key已存在时,更新元素,否则在空位置中插入元素bool HashTableInsert(HashTable Hash, KeyType Key, EleType Data){int pos = 0, i = 0;HashBucket *p = NULL, *s = NULL;if( NULL == Hash )return false;pos = HashFunc(Key);//求Key所对应的基桶p = Hash + pos;//指向该基桶if( true == UpdataBucket(p, Key, Data) )//桶内元素更新成功return true;//基桶内已没有空位置while (NULL != p->Bucket)//在溢出桶内寻找位置{p = p->Bucket;if (true == UpdataBucket(p, Key, Data))//桶内元素更新成功return true;}//在已查找过的桶内都未能找到合适的位置,创建一个新的溢出桶来存储元素s = (HashBucket *)malloc(sizeof(HashBucket));if( NULL == s )return false;for (i = 0; i < BUCKET_SIZE; ++i)//初始化桶{s->Data[i].Key = INVALID_VALUE;s->Data[i].Val = INVALID_VALUE;}s->Bucket = NULL;//初始化桶s->Data[0].Key = Key;//将Key值对存储在溢出桶首位置中s->Data[0].Val = Data;p->Bucket = s;//将新桶挂接上去return true;}EleType *HashTableFind(HashTable Hash, KeyType Key){_ElementNode_ *p = HashTableFind_(Hash, Key);if( NULL != p )return &(p->Val);//查找到元素,返回元素的值成员地址return NULL;}bool HashTableDelete(HashTable Hash, KeyType Key){_ElementNode_ *p = HashTableFind_(Hash, Key);if( NULL != p ){p->Key = INVALID_VALUE;//查找、插入都是根据Key值来的,因此只需覆盖Key即可return true;}elsereturn false;}void HashTableDestroy(HashTable *Hash){HashBucket *p = NULL, *q = NULL, *s = NULL;int i = 0;if( NULL == Hash )return ;p = *Hash;//指向首个基桶for (i = 0; i < HASHTABLE_SIZE; ++i)//释放全部基桶{q = p->Bucket;//指向某个基桶的溢出桶所构成的链表while (NULL != q)//释放溢出桶所构成的链表{s = q->Bucket;p->Bucket = s;free(q);q = s;}++p;}free(*Hash);//释放全部基桶*Hash = NULL;}



//main.c

#include "HashTable.h"#include <stdio.h>int main(int argc, char **argv){HashTable hash = NULL;EleType *e = NULL;//KeyType KeyArray[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//EleType EleArray[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };KeyType KeyArray[] ={ 1, 18, 35, 52, 69, 86, 103, 120, 137, 171, 171, 188, 205, 222,  239, 255, 273 };EleType EleArray[] ={ 10, 180, 350, 520, 690, 860, 1030, 1200, 1370, 1710, 0, 1880, 2050, 2220, 2390, 2550, 2730 };int size = sizeof(KeyArray) / sizeof(KeyType);int i = 0;bool ret = true;KeyType key = 0;HashTableInit(&hash);for (i = 0; i < size && ret; ++i)ret = HashTableInsert(hash, KeyArray[i], EleArray[i]);key = 156;e = HashTableFind(hash, key);if( NULL != e ){printf("值为%d\n", *e);*e = 123;printf("修改后\n");e = HashTableFind(hash, key);if (NULL != e)printf("值为%d\n", *e);}elseprintf("键%d不存在\n", key);key = 171;ret = HashTableDelete(hash, key);if( true == ret ){printf("键值对%d删除成功\n", key);e = HashTableFind(hash, key);if (NULL != e)printf("值为%d\n", *e);elseprintf("键%d不存在\n", key);}elseprintf("键%d不存在\n", key);HashTableDestroy(&hash);return 0;}





原创粉丝点击