数据结构之哈希表

来源:互联网 发布:数据库发展历史 编辑:程序博客网 时间:2024/06/01 20:50

仅给出一个以“除留余数法”+“开放定址法(线性探测再散列)”实现的哈希表代码:

#pragma once#define SUCCESS 1#define UNSUCCESS 0#define DUPLICATE -1#define NULLKEY -111#define OK 1#define ERROR -1#define EQ(a,b) ((a)==(b))#define LT(a,b) ((a)< (b))#define LQ(a,b) ((a)<=(b))typedef int KeyType;typedef int info;typedef struct{KeyType key;//info otherinfo;}ElemType;typedef struct{ElemType *elem;int count; //当前hash表元素个数int sizeindex; //hashsize[sizeindex]为当前hash表当前容量}HashTable;int InitHashTable(HashTable &H); // 构造一个空的哈希表void DestroyHashTable(HashTable &H);int Hash(KeyType K); // 除留余数法(m为表长,全局变量)void collision(int &p,int d);// 开放定址法处理冲突:线性探测再散列int SearchHash(HashTable H,KeyType K,int &p,int &c);   //搜索的是关键字int InsertHash(HashTable &H,ElemType e);   //插入的是元素void RecreateHashTable(HashTable &H) /* 重建哈希表 */;void TraverseHash(HashTable H);

#include "hash.h"#include <stdio.h>#include <stdlib.h>int hashsize[]={13,19,29,37}; // 哈希表容量递增表,一个合适的素数序列int m = 0; // 哈希表表长,全局变量int InitHashTable(HashTable &H)// 构造一个空的哈希表{ int i;H.count=0; // 当前元素个数为0H.sizeindex=0; // 初始存储容量为hashsize[0]m = hashsize[0];H.elem=(ElemType*)malloc(m*sizeof(ElemType));if(!H.elem)exit(0); // 存储分配失败for(i=0;i<m;i++)H.elem[i].key=NULLKEY; // 未填记录的标志return OK;}  //InitHashTablevoid DestroyHashTable(HashTable &H) //哈希表H存在,销毁哈希表H{ if (H.elem != NULL) free(H.elem);H.elem=NULL;H.count=0;H.sizeindex=0;} //DestroyHashTableint Hash(KeyType K)   // 除留余数法(m为表长,全局变量){ return K%m;} //Hashvoid collision(int &p,int d) // 开放定址法处理冲突:线性探测再散列{ p=(p+d)%m;} //collision//在开放地址hashH中查找关键字K的元素,若查找成功,以p指示待查元素数据在表中位置并返回SUCCESS//否则以p指示插入位置并返回UNSUCCESS//c用以计冲突次数,其初值为0,供建表插入时参考int SearchHash(HashTable H,KeyType K,int &p,int &c){    p=Hash(K); //构造哈希函数while(H.elem[p].key!=NULLKEY&&!EQ(K,H.elem[p].key)){collision(p,++c); //冲突检测if(c>=m) break;}if(H.elem[p].key!=NULLKEY&&EQ(K,H.elem[p].key))return SUCCESS;else return UNSUCCESS;}//SearchHashint InsertHash(HashTable &H,ElemType e){ // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK;若冲突次数过大,则重建哈希表int c,p;c=0;if(SearchHash(H,e.key,p,c)) // 表中已有与e有相同关键字的元素return DUPLICATE;else if(c<hashsize[H.sizeindex]/2) // 冲突次数c未达到上限,(c的阀值可调){// 插入eH.elem[p]=e;++H.count;return OK;}elseRecreateHashTable(H); // 重建哈希表return ERROR;}void RecreateHashTable(HashTable &H) // 重建哈希表{ int i,count=H.count;ElemType *p,*elem=(ElemType*)malloc(count*sizeof(ElemType));p=elem;printf("重建哈希表\n");for(i=0;i<m;i++) // 保存原有的数据到临时申请了空间的elem中if((H.elem+i)->key!=NULLKEY) // 该单元有数据*p++=*(H.elem+i);H.count=0;H.sizeindex++; // 增大存储容量m=hashsize[H.sizeindex];p=(ElemType*)realloc(H.elem,m*sizeof(ElemType));if(!p)exit(-1); // 存储分配失败H.elem=p;for(i=0;i<m;i++)H.elem[i].key=NULLKEY; // 未填记录的标志(初始化)for(p=elem;p<elem+count;p++) // 将原有的数据按照新的表长插入到重建的哈希表中InsertHash(H,*p);free(elem);elem = NULL;}//RecreateHashTablevoid TraverseHash(HashTable H){int i;for (i = 0; i < m; i++)printf("%2d ", i);putchar('\n');for (i = 0; i < m; i++)if (H.elem[i].key != NULLKEY)printf("%2d ", H.elem[i].key);elseprintf("   ");putchar('\n');putchar('\n');}

测试代码:

int main(){HashTable H;int i;KeyType arr[] = {19, 14, 23, 01, 68, 20, 84, 27, 55, 11, 10, 79};  //关键字int n = sizeof(arr)/sizeof(arr[0]);InitHashTable(H);ElemType e;for (i = 0; i < n - 1; i++)//n{e.key = arr[i];InsertHash(H, e);   //插入的是元素printf("插入 %d 后:\n", e.key);TraverseHash(H);}printf("Hash表元素为:\n");TraverseHash(H);for (i = 0; i < n; i++){int p = 0, c = 0;int ret = SearchHash(H, arr[i], p, c);//查找的是关键字if(ret)printf("查找 %2d 成功, p = %2d, key = %2d, c = %d\n",arr[i], p, H.elem[p].key, c);else printf("查找 %d 失败\n", arr[i]);}DestroyHashTable(H);getchar();return 1;}

1 0
原创粉丝点击