哈希表
2016-05-26 10:17
351 查看
#include "stdio.h" #include "stdlib.h" #define SUCCESS 1 #define UNSUCCESS 0 #define DUPLICATE -1 #define OK 1 #define ERROR -1 #define EQ(a,b) ((a)==(b)) #define LT(a,b) ((a)< (b)) #define LQ(a,b) ((a)<=(b)) #define BT(a,b) ((a)> (b)) #define NULLKEY -111 int hashsize[]={11,19,29,37}; // 哈希表容量递增表, //一个合适的素数序列 int m=0; // 哈希表表长,全局变量 typedef int KeyType; typedef int info; typedef struct { KeyType key; //info otherinfo; }ElemType; typedef struct { ElemType *elem; int count; int sizeindex; }HashTable; int InitHashTable(HashTable &H) { // 操作结果: 构造一个空的哈希表 int i; H.count=0; // 当前元素个数为0 H.sizeindex=0; // 初始存储容量为hashsize[H.sizeindex] 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; } void DestroyHashTable(HashTable &H) { // 初始条件: 哈希表H存在。操作结果: 销毁哈希表H free(H.elem); H.elem=NULL; H.count=0; H.sizeindex=0; }//DestroyHashTable int Hash(KeyType K) { // 一个简单的哈希函数(m为表长,全局变量) //除留余数法 return K%m; }//Hash void collision(int &p,int d) // 线性探测再散列 { // 开放定址法处理冲突 p=(p+d)%m; }//collision 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); //探测下一个位置p if(c>=m) break; } if(EQ(K,H.elem[p].key)) //查找成功,p返回待查数据元素位置 return SUCCESS; else //查找不成功(H.elem[p].key==NULLKEY) return UNSUCCESS; //p返回的是插入位置 }//SearchHash int InsertHash(HashTable &H,ElemType e); 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.coun重置为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); }//RecreateHashTable int InsertHash(HashTable &H,ElemType e) { // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回OK; // 若冲突次数过大,则重建哈希表 int c,p; c=0; if(SearchHash(H,e.key,p,c)) // 表中已有与e相同的元素 return DUPLICATE; //SUCCESS=1 else if(c<hashsize[H.sizeindex]/2) // 冲突次数c未达到上限,(c的阀值可调) { // 插入e H.elem[p]=e; ++H.count; return OK; } else RecreateHashTable(H); // 冲突次数c达到上限,将原来的哈希表重建,不包括现在正要插入的数据e return ERROR; } int InsertHashD(HashTable &H) { ElemType e; printf("input the data until -1\n"); scanf("%d",&e.key); while(e.key!=-1) { InsertHash(H,e); scanf("%d",&e.key); }//while return 1; }//InsertHashD int SearchHashD(HashTable &H) { KeyType key; int p=0,c=0; printf("input the data you want to search:\n"); scanf("%d",&key); if(SearchHash(H,key,p,c)) printf("the location is %d,%d\n",p,H.elem[p].key); else printf("Search Failed!\n"); return 1; }//SearchHashD void print(int p,ElemType r) { printf("address=%d (%d)\n",p,r.key); }//print void TraverseHash(HashTable H,void(*Vi)(int,ElemType)) { // 按哈希地址的顺序遍历哈希表 printf("哈希地址0~%d\n",m-1); for(int i=0;i<m;i++) if(H.elem[i].key!=NULLKEY) // 有数据 Vi(i,H.elem[i]); }//TraverseHash void TraverseHashD(HashTable &H) { TraverseHash(H,print); }//TraverseHashD int main() { HashTable H; InitHashTable(H); //初始化 InsertHashD(H); //构造哈希表 //SearchHashD(H); //查找 TraverseHashD(H); //遍历 DestroyHashTable(H); //销毁 return 1; }
相关文章推荐
- C++程序设计语言练习5.12 对比string和C字符串的优劣
- 第二次冲刺阶段第三天
- Java+MySQL实现网络爬虫程序
- Google又被人“盯”上了?九爱到底想干吗?
- backface-visibility什么意思
- Android之代码混淆
- 【A+项目】业主导入工具使用说明
- 开源新闻速递:并没有什么用的 Chromium OS
- 开源新闻速递:并没有什么用的 Chromium OS
- Using cordova-camera plugin in your Ionic 2 Apps
- Numpy之文件存取
- Android Studio常用插件
- innerHTML的性能问题
- Android开发环境搭建教程
- Linux及安全实践二——模块
- php常用字符串操作函数
- 【云计算】Docker build解决父镜像层级关系过多问题:Cannot create container with more than 127 parents
- MotionEvent和TouchSlop
- Leap Motion架构
- php编译可扩展模块