查看: 4418|回复: 4
收起左侧

[分享] 拉链法实现哈希表 和 哈希表 开放定址法

[复制链接]
chujunci
发表于 2011-12-31 22:32:54 | 显示全部楼层 |阅读模式
  1. /*
  2. *哈希表 拉链法
  3. */  
  4. #include<stdio.h>   
  5. #include<stdlib.h>   
  6.   
  7. #define MinTableSize 10   
  8.   
  9. typedef int ElemType;  
  10. typedef unsigned int Index;  
  11.   
  12. typedef struct ListNode  
  13. {  
  14.     ElemType element;  
  15.     struct  ListNode *next;  
  16. }*Position;  
  17.   
  18. typedef Position List;  
  19.   
  20. /* List *TheList will be an array of lists, allocated later */  
  21. /* The lists use headers (for simplicity), */  
  22. /* though this wastes space */  
  23. typedef struct HashTbl  
  24. {  
  25.     int TableSize;  
  26.      List *TheLists;  
  27. }*HashTable;  
  28.   
  29. int NextPrime(int N)  
  30. {  
  31.     int i;  
  32.   
  33.     if(N%2==0)  
  34.         N++;  
  35.     for(;;N+=2)  
  36.     {  
  37.         for(i=3;i*i<=N;i+=2)  
  38.             if(N%i==0)  
  39.                 return 0;  
  40.         return N;     
  41.     }  
  42. }  
  43.   
  44. /*Hash function for ints*/  
  45. Index Hash(ElemType Key,int TableSize)  
  46. {  
  47.     return Key%TableSize;  
  48. }  
  49.   
  50. HashTable InitializeTable(int TableSize)  
  51. {  
  52.     HashTable H;  
  53.     int i;  
  54.   
  55.     if(TableSize<MinTableSize)  
  56.     {  
  57.         printf("Table size too small!\n");  
  58.         return NULL;  
  59.     }  
  60.       
  61.     /*Allocate table*/  
  62.     H=(HashTable)malloc(sizeof(struct HashTbl));  
  63.     if(NULL==H)  
  64.       printf("Out of space!!!\n");  
  65.   
  66.     H->TableSize=NextPrime(TableSize);  
  67.       
  68.     /*Allocate array of lists*/  
  69.     H->TheLists=(List *)malloc(sizeof(List)*H->TableSize);  
  70.     if(NULL==H->TheLists)  
  71.     {  
  72.       printf("Out of space!!!\n");  
  73.       free(H);  
  74.       return NULL;  
  75.     }  
  76.     /*Allocate list  headers*/  
  77.     for(i=0;i<H->TableSize;i++)  
  78.     {  
  79.         H->TheLists[i]=(Position)malloc(sizeof(struct ListNode));  
  80.         if(NULL==H->TheLists[i])  
  81.             printf("Out of space!!!\n");  
  82.         else  
  83.             H->TheLists[i]->next=NULL;  
  84.   
  85.         H->TheLists[i]->element=0;//哈希表中所有元素的key初始化为0   
  86.     }  
  87.   
  88.     return H;  
  89. }  
  90.   
  91. Position Find(ElemType Key,HashTable H)  
  92. {  
  93.     Position p;  
  94.     List L;  
  95.   
  96.     L=H->TheLists[Hash(Key,H->TableSize)];  
  97.     p=L->next;  
  98.     while(p!=NULL&&p->element!=Key)/*Probably need strcmp!!*/  
  99.         p=p->next;  
  100.   
  101.     return p;  
  102. }  
  103.   
  104. void Insert(ElemType Key,HashTable H)  
  105. {  
  106.     Position pos,newCell;  
  107.     List L;  
  108.   
  109.     pos=Find(Key,H);  
  110.     if(NULL==pos)/*Key is not found*/  
  111.     {  
  112.         newCell=(Position)malloc(sizeof(struct ListNode));  
  113.         if(NULL==newCell)  
  114.           printf("Out of space!!!");      
  115.         else  
  116.         {  
  117.             L=H->TheLists[Hash(Key,H->TableSize)];  
  118.             newCell->next=L->next;  
  119.             newCell->element=Key;/*Probably need strcpy*/  
  120.             L->next=newCell;  
  121.         }  
  122.     }  
  123. }  
  124.   
  125. void DestroyTable(HashTable H)  
  126. {  
  127.     int i;  
  128.   
  129.     for(i=0;i<H->TableSize;i++)  
  130.     {  
  131.         Position p=H->TheLists[i];  
  132.         Position temp;  
  133.   
  134.         while(p!=NULL)  
  135.         {  
  136.             temp=p->next;  
  137.             free(p);  
  138.             p=temp;  
  139.         }  
  140.     }  
  141.     free(H->TheLists);  
  142.     free(H);  
  143. }  
  144.   
  145. void printHash(HashTable H,int len)  
  146. {  
  147.     int i;  
  148.     for(i=0;i<len;i++)  
  149.     {  
  150.         Position p=H->TheLists[i];  
  151.         while(p)  
  152.         {  
  153.             printf("address=%d value=%d\n",i,p->element);  
  154.             p=p->next;  
  155.         }     
  156.     }  
  157.   
  158. }  
  159. int main()  
  160. {  
  161.       
  162.     HashTable H;  
  163.     Position p=NULL;  
  164.     int array[]={19,14,23,01,68,20,84,27,55,11,10,79};  
  165.     int len=sizeof(array)/sizeof(array[0]);  
  166.     int i;  
  167.     ElemType k;  
  168.                
  169.     H=InitializeTable(len);  
  170.     for(i=0;i<len;i++)  
  171.     {  
  172.         Insert(array[i],H);   
  173.     }  
  174.     printHash(H,len);  
  175.     printf("\n\n");  
  176.       
  177.     printf("please input the value which need find:");  
  178.     scanf("%d",&k);  
  179.     p=Find(k,H);  
  180.     if(p)  
  181.       printf("%d",p->element);  
  182.     else  
  183.       printf("cannot find the value!");  
  184.     printf("\n\n");  
  185.       
  186.     printf("free the table\n");  
  187.     DestroyTable(H);  
  188.     printf("it's done!!!");  
  189.     printf("\n\n");  
  190.   
  191.     return 0;  
  192. }  
复制代码
  1. /*
  2. *哈希表
  3. */  
  4. #include<stdio.h>   
  5. #include<stdlib.h>   
  6.   
  7. #define NULLKEY 0//0为无记录标志   
  8. #define N 10//数据元素个数   
  9.   
  10. typedef int KeyType;//设关键字域为整型   
  11. typedef struct   
  12. {  
  13.     KeyType key;  
  14.     int ord;  
  15. }ElemType;//数据元素类型   
  16.   
  17. #define EQ(a,b) ((a)==(b))   
  18.   
  19. int hashsize[]={11,19,29,37};//哈希表容量递增表 一个合适的素数序列   
  20. int m=0;//哈希表表长 全局变量   
  21.   
  22. typedef struct  
  23. {  
  24.     ElemType *elem;//数据元素存储基址 动态分配数组   
  25.     int count;//当前数据元素个数   
  26.     int size_index;//hashsize[size_index]为当前容量   
  27. }HashTable;  
  28.   
  29.   
  30. #define SUCCESS 1   
  31. #define UNSUCCESS 0   
  32. #define DUPLICATE -1   
  33.   
  34. /* 操作结果: 构造一个空的哈希表 */  
  35. int initHashTable(HashTable *H)  
  36. {  
  37.     int i;  
  38.   
  39.     (*H).count=0;//当前元素个数为0   
  40.     (*H).size_index=0;//初始存储容量为hashsize[0]   
  41.     m=hashsize[0];  
  42.     (*H).elem=(ElemType *)malloc(m*sizeof(ElemType));  
  43.     if(!(*H).elem)  
  44.         exit(0);//存储分配失败   
  45.     for(i=0;i<m;i++)  
  46.         (*H).elem[i].key=NULLKEY;//未填记录的标记   
  47.   
  48.     return 1;  
  49. }  
  50.   
  51. /* 初始条件:哈希表H存在*/  
  52. /* 操作结果:销毁哈希表H*/  
  53. void destroyHashTable(HashTable *H)  
  54. {  
  55.     free((*H).elem);  
  56.     (*H).elem=NULL;  
  57.     (*H).count=0;  
  58.     (*H).size_index=0;  
  59. }  
  60.   
  61. /* 一个简单的哈希函数(m为表长 全局变量)*/  
  62. unsigned Hash(KeyType K)  
  63. {  
  64.     return K%m;  
  65. }  
  66.   
  67. /*线性探测再散列*/  
  68. void collision(int *p,int d)  
  69. {  
  70.     *p=(*p+d)%m;//开放定址法处理冲突   
  71. }  
  72.   
  73. /* 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据 */  
  74. /* 元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS */  
  75. /* c用以计冲突次数,其初值置零,供建表插入时参考 */  
  76. int searchHash(HashTable H,KeyType K,int *p,int *c)  
  77. {  
  78.     *p=Hash(K);//求得哈希地址   
  79.     while(H.elem[*p].key!=NULLKEY&&!EQ(K,H.elem[*p].key))//该位置中填有记录 并且关键字不相等   
  80.     {  
  81.         (*c)++;  
  82.         if(*c<m)  
  83.             collision(p,*c);//求得下一探查地址p   
  84.         else  
  85.             break;  
  86.     }  
  87.     if EQ(K,H.elem[*p].key)  
  88.         return SUCCESS;//查找成功 p返回待查数据元素位置   
  89.     else  
  90.         return UNSUCCESS;//查找不成功(H.elem[p].key==NULLKEY p返回的是插入的位置)   
  91. }  
  92.   
  93. int insertHash(HashTable *,ElemType);//对函数的声明   
  94.   
  95. void recreateHashTable(HashTable *H)//重建哈希表   
  96. {  
  97.     int i,count=(*H).count;  
  98.   
  99.     ElemType *p,*elem=(ElemType *)malloc(count*sizeof(ElemType));  
  100.   
  101.     p=elem;  
  102.   
  103.     printf("重建哈希表\n");  
  104.     for(i=0;i<m;i++)//保存原有的数据到elem中   
  105.         if(((*H).elem+i)->key!=NULLKEY)//该单元有数据   
  106.             *p++=*((*H).elem+i);  
  107.     (*H).count=0;  
  108.     (*H).size_index++;//增大存储容量   
  109.     m=hashsize[(*H).size_index];  
  110.     p=(ElemType *)realloc((*H).elem,m*sizeof(ElemType));  
  111.     if(!p)  
  112.         exit(0);//存储分配失败   
  113.     (*H).elem=p;  
  114.   
  115.     for(i=0;i<m;i++)  
  116.         (*H).elem[i].key=NULLKEY;//未填记录买的标志(初始化)   
  117.     for(p=elem;p<elem+count;p++)//将原有的数据按照新的表长插入到重建的哈希表中   
  118.         insertHash(H,*p);  
  119. }  
  120.   
  121. /* 查找不成功时插入数据元素e到开放定址哈希表H中,并返回1 */  
  122. /* 若冲突次数过大,则重建哈希表 */  
  123. int insertHash(HashTable *H,ElemType e)  
  124. {  
  125.     int c,p;  
  126.   
  127.     c=0;  
  128.     if(searchHash(*H,e.key,&p,&c))//表中已有与e有相同关键字的元素   
  129.         return DUPLICATE;  
  130.     else if(c<hashsize[(*H).size_index]/2)//冲突次数c未达到上线 c的阀值可调   
  131.     {  
  132.         (*H).elem[p]=e;//插入e   
  133.         ++(*H).count;  
  134.   
  135.         return 1;  
  136.     }  
  137.     else  
  138.         recreateHashTable(H);//重建哈希表   
  139.   
  140. return 0;  
  141. }  
  142.   
  143. /* 按哈希地址的顺序遍历哈希表 */  
  144. void traverseHash(HashTable H,void(*Vi)(int ,ElemType))  
  145. {  
  146.     int i;  
  147.   
  148.     printf("哈希地址0~%d\n",m-1);  
  149.     for(i=0;i<m;i++)  
  150.     {  
  151.         if(H.elem[i].key!=NULLKEY)//有数据   
  152.             Vi(i,H.elem[i]);  
  153.     }  
  154. }  
  155.   
  156. /* 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据 */  
  157. /* 元素在表中位置,并返回SUCCESS;否则,返回UNSUCCESS */  
  158. int find(HashTable H,KeyType K,int *p)  
  159. {  
  160.     int c=0;  
  161.   
  162.     *p=Hash(K);//求得哈希地址   
  163.     while(H.elem[*p].key!=NULLKEY&&!EQ(K,H.elem[*p].key))//该位置中填有记录.并且关键字不相等   
  164.      {   
  165.         c++;  
  166.         if(c<m)  
  167.           collision(p,c); //求得下一探查地址p   
  168.         else  
  169.           return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)   
  170.      }  
  171.      if EQ(K,H.elem[*p].key)  
  172.         return SUCCESS; //查找成功,p返回待查数据元素位置   
  173.      else  
  174.         return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)   
  175.   
  176. }  
  177.   
  178. void printHash(int p,ElemType r)  
  179. {  
  180.     printf("address=%d (%d %d)\n",p,r.key,r.ord);  
  181. }  
  182. int main()  
  183. {  
  184.      ElemType r[N]={{17,1},{60,2},{29,3},{38,4},{1,5},{2,6},{3,7},{4,8},{60,9},{13,10}};  
  185.      HashTable h;  
  186.      int i,p;  
  187.      int j;  
  188.      KeyType k;  
  189.   
  190.      initHashTable(&h);  
  191.      for(i=0;i<N-1;i++)//插入前N-1个记录   
  192.      {  
  193.          j=insertHash(&h,r[i]);  
  194.          if(j==DUPLICATE)  
  195.              printf("表中已有关键字尾%d的记录 无法再插入记录(%d %d)\n",r[i].key,r[i].key,r[i].ord);  
  196.      }  
  197.   
  198.      printf("按哈希地址的顺序遍历哈希表\n");  
  199.      traverseHash(h,printHash);  
  200.      printf("\n\n");  
  201.   
  202.      printf("请输入带查找记录的关键字:");  
  203.      scanf("%d",&k);  
  204.      j=find(h,k,&p);  
  205.      if(j==SUCCESS)  
  206.          printHash(p,h.elem[p]);  
  207.      else  
  208.          printf("没找到\n");  
  209.     printf("\n\n");  
  210.   
  211.      j=insertHash(&h,r[i]);//插入第N个记录   
  212.      if(j==0)//j==ERROR 重建哈希表   
  213.          j=insertHash(&h,r[i]);//重建哈希表后重新插入第N个记录   
  214.   
  215.      printf("按哈希地址的顺序遍历重建后的哈希表\n");  
  216.      traverseHash(h,printHash);  
  217.      printf("\n\n");  
  218.   
  219.      printf("请输入带查找记录的关键字:");  
  220.      scanf("%d",&k);  
  221.      j=find(h,k,&p);  
  222.      if(j==SUCCESS)  
  223.          printHash(p,h.elem[p]);  
  224.      else  
  225.          printf("没找到\n");  
  226.     printf("\n\n");  
  227.   
  228.      destroyHashTable(&h);  
  229.      printf("哈希表销毁成功!");  
  230.      printf("\n\n");  
  231.   
  232.      return 0;  
  233. }  
复制代码
-oAo-
发表于 2011-12-31 22:40:18 | 显示全部楼层
看不懂
yjwfdc
头像被屏蔽
发表于 2012-1-1 00:28:48 | 显示全部楼层
不知道用途
chen月
发表于 2012-1-1 00:48:20 | 显示全部楼层
卡饭怎么还有这么牛的问题?
goodliukun
发表于 2012-1-1 03:11:26 | 显示全部楼层
技术贴?
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2025-1-22 12:46 , Processed in 0.144507 second(s), 16 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表