zoukankan      html  css  js  c++  java
  • 数据结构哈希表(转)

    数据结构哈希表

    参考代码如下:

     

    [plain] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /*  
    2.     名称:哈希表   
    3.     语言:数据结构C语言版   
    4.     编译环境:VC++ 6.0  
    5.     日期: 2014-3-26   
    6. */  
    7.   
    8.   
    9. #include <stdio.h>  
    10. #include <malloc.h>  
    11. #include <windows.h>  
    12.   
    13.   
    14. #define NULLKEY 0   // 0为无记录标志   
    15. #define N 10        // 数据元素个数   
    16.   
    17. typedef int KeyType;// 设关键字域为整型   
    18.   
    19. typedef struct  
    20. {  
    21.     KeyType key;  
    22.     int ord;  
    23. }ElemType; // 数据元素类型   
    24.   
    25. // 开放定址哈希表的存储结构   
    26. int hashsize[]={11,19,29,37}; // 哈希表容量递增表,一个合适的素数序列   
    27. int m=0; // 哈希表表长,全局变量   
    28.   
    29. typedef struct  
    30. {  
    31.     ElemType *elem; // 数据元素存储基址,动态分配数组   
    32.     int count; // 当前数据元素个数   
    33.     int sizeindex; // hashsize[sizeindex]为当前容量   
    34. }HashTable;  
    35.   
    36. #define SUCCESS 1  
    37. #define UNSUCCESS 0  
    38. #define DUPLICATE -1  
    39.   
    40.   
    41. // 构造一个空的哈希表  
    42. int InitHashTable(HashTable *H)  
    43. {    
    44.     int i;  
    45.     (*H).count=0; // 当前元素个数为0   
    46.     (*H).sizeindex=0; // 初始存储容量为hashsize[0]   
    47.     m=hashsize[0];  
    48.     (*H).elem=(ElemType*)malloc(m*sizeof(ElemType));  
    49.     if(!(*H).elem)  
    50.         exit(0); // 存储分配失败   
    51.     for(i=0;i<m;i++)  
    52.         (*H).elem[i].key=NULLKEY; // 未填记录的标志   
    53.       
    54.     return 1;  
    55. }  
    56.   
    57. //  销毁哈希表H  
    58. void DestroyHashTable(HashTable *H)  
    59. {   
    60.     free((*H).elem);  
    61.     (*H).elem=NULL;  
    62.     (*H).count=0;  
    63.     (*H).sizeindex=0;  
    64. }  
    65.   
    66. // 一个简单的哈希函数(m为表长,全局变量)  
    67. unsigned Hash(KeyType K)  
    68. {   
    69.     return K%m;  
    70. }  
    71.   
    72. // 开放定址法处理冲突  
    73. void collision(int *p,int d) // 线性探测再散列   
    74. {    
    75.     *p=(*p+d)%m;  
    76. }  
    77.   
    78. // 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据   
    79. // 元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS   
    80. // c用以计冲突次数,其初值置零,供建表插入时参考。  
    81. int SearchHash(HashTable H,KeyType K,int *p,int *c)  
    82. {  
    83.     *p=Hash(K); // 求得哈希地址   
    84.     while(H.elem[*p].key!=NULLKEY&&!(K == H.elem[*p].key))  
    85.     {  
    86.         // 该位置中填有记录.并且关键字不相等   
    87.         (*c)++;  
    88.         if(*c<m)  
    89.             collision(p,*c); // 求得下一探查地址p   
    90.         else  
    91.             break;  
    92.     }  
    93.     if (K == H.elem[*p].key)  
    94.         return SUCCESS; // 查找成功,p返回待查数据元素位置   
    95.     else  
    96.         return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置   
    97. }  
    98.   
    99. int InsertHash(HashTable *,ElemType); // 对函数的声明   
    100.   
    101. // 重建哈希表  
    102. void RecreateHashTable(HashTable *H) // 重建哈希表   
    103. {   
    104.     int i,count=(*H).count;  
    105.     ElemType *p,*elem=(ElemType*)malloc(count*sizeof(ElemType));  
    106.     p=elem;  
    107.     printf("重建哈希表 ");  
    108.     for(i=0;i<m;i++) // 保存原有的数据到elem中   
    109.         if(((*H).elem+i)->key!=NULLKEY) // 该单元有数据   
    110.             *p++=*((*H).elem+i);  
    111.     (*H).count=0;  
    112.     (*H).sizeindex++; // 增大存储容量   
    113.     m=hashsize[(*H).sizeindex];  
    114.     p=(ElemType*)realloc((*H).elem,m*sizeof(ElemType));  
    115.     if(!p)  
    116.         exit(0); // 存储分配失败   
    117.     (*H).elem=p;  
    118.     for(i=0;i<m;i++)  
    119.         (*H).elem[i].key=NULLKEY; // 未填记录的标志(初始化)   
    120.     for(p=elem;p<elem+count;p++) // 将原有的数据按照新的表长插入到重建的哈希表中   
    121.         InsertHash(H,*p);  
    122. }  
    123.   
    124. // 查找不成功时插入数据元素e到开放定址哈希表H中,并返回1;   
    125. // 若冲突次数过大,则重建哈希表。  
    126. int InsertHash(HashTable *H,ElemType e)  
    127. {  
    128.     int c,p;  
    129.     c=0;  
    130.     if(SearchHash(*H,e.key,&p,&c)) // 表中已有与e有相同关键字的元素   
    131.         return DUPLICATE;  
    132.     else if(c<hashsize[(*H).sizeindex]/2) // 冲突次数c未达到上限,(c的阀值可调)   
    133.     {  
    134.         // 插入e   
    135.         (*H).elem[p]=e;  
    136.         ++(*H).count;  
    137.         return 1;  
    138.     }  
    139.     else  
    140.         RecreateHashTable(H); // 重建哈希表   
    141.       
    142.     return 0;  
    143. }  
    144.   
    145. // 按哈希地址的顺序遍历哈希表  
    146. void TraverseHash(HashTable H,void(*Vi)(int,ElemType))  
    147. {    
    148.     int i;  
    149.     printf("哈希地址0~%d ",m-1);  
    150.     for(i=0;i<m;i++)  
    151.         if(H.elem[i].key!=NULLKEY) // 有数据   
    152.             Vi(i,H.elem[i]);  
    153. }  
    154.   
    155. // 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据   
    156. // 元素在表中位置,并返回SUCCESS;否则,返回UNSUCCESS   
    157. int Find(HashTable H,KeyType K,int *p)  
    158. {  
    159.     int c=0;  
    160.     *p=Hash(K); // 求得哈希地址   
    161.     while(H.elem[*p].key!=NULLKEY&&!(K == H.elem[*p].key))  
    162.     { // 该位置中填有记录.并且关键字不相等   
    163.         c++;  
    164.         if(c<m)  
    165.             collision(p,c); // 求得下一探查地址p   
    166.         else  
    167.             return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)   
    168.     }  
    169.     if (K == H.elem[*p].key)  
    170.         return SUCCESS; // 查找成功,p返回待查数据元素位置   
    171.     else  
    172.         return UNSUCCESS; // 查找不成功(H.elem[p].key==NULLKEY)   
    173. }  
    174.   
    175.   
    176. void print(int p,ElemType r)  
    177. {  
    178.     printf("address=%d (%d,%d) ",p,r.key,r.ord);  
    179. }  
    180.   
    181. int main()  
    182. {  
    183.     ElemType r[N] = {  
    184.         {17,1},{60,2},{29,3},{38,4},{1,5},  
    185.         {2,6},{3,7},{4,8},{60,9},{13,10}  
    186.     };  
    187.     HashTable h;  
    188.     int i, j, p;  
    189.     KeyType k;  
    190.       
    191.     InitHashTable(&h);  
    192.     for(i=0;i<N-1;i++)  
    193.     {  
    194.         // 插入前N-1个记录   
    195.         j=InsertHash(&h,r[i]);  
    196.         if(j==DUPLICATE)  
    197.             printf("表中已有关键字为%d的记录,无法再插入记录(%d,%d) ",  
    198.                 r[i].key,r[i].key,r[i].ord);  
    199.     }  
    200.     printf("按哈希地址的顺序遍历哈希表: ");  
    201.     TraverseHash(h,print);  
    202.     printf("请输入待查找记录的关键字: ");  
    203.     scanf("%d",&k);  
    204.     j=Find(h,k,&p);  
    205.     if(j==SUCCESS)  
    206.         print(p,h.elem[p]);  
    207.     else  
    208.         printf("没找到 ");  
    209.     j=InsertHash(&h,r[i]); // 插入第N个记录   
    210.     if(j==0) // 重建哈希表   
    211.         j=InsertHash(&h,r[i]); // 重建哈希表后重新插入第N个记录   
    212.     printf("按哈希地址的顺序遍历重建后的哈希表: ");  
    213.     TraverseHash(h,print);  
    214.     printf("请输入待查找记录的关键字: ");  
    215.     scanf("%d",&k);  
    216.     j=Find(h,k,&p);  
    217.     if(j==SUCCESS)  
    218.         print(p,h.elem[p]);  
    219.     else  
    220.         printf("没找到 ");  
    221.     DestroyHashTable(&h);  
    222.       
    223.     system("pause");  
    224.     return 0;   
    225. }  
    226.   
    227. /*  
    228. 输出效果:  
    229.   
    230. 表中已有关键字为60的记录,无法再插入记录(60,9)  
    231. 按哈希地址的顺序遍历哈希表:  
    232. 哈希地址0~10  
    233. address=1 (1,5)  
    234. address=2 (2,6)  
    235. address=3 (3,7)  
    236. address=4 (4,8)  
    237. address=5 (60,2)  
    238. address=6 (17,1)  
    239. address=7 (29,3)  
    240. address=8 (38,4)  
    241. 请输入待查找记录的关键字: 17  
    242. address=6 (17,1)  
    243. 重建哈希表  
    244. 按哈希地址的顺序遍历重建后的哈希表:  
    245. 哈希地址0~18  
    246. address=0 (38,4)  
    247. address=1 (1,5)  
    248. address=2 (2,6)  
    249. address=3 (3,7)  
    250. address=4 (4,8)  
    251. address=6 (60,2)  
    252. address=10 (29,3)  
    253. address=13 (13,10)  
    254. address=17 (17,1)  
    255. 请输入待查找记录的关键字: 13  
    256. address=13 (13,10)  
    257. 请按任意键继续. . .  
    258.   
    259. */   


    运行结果如下:

     

  • 相关阅读:
    野指针
    MFC动态创建控件及其消息响应函数
    关于CString总结
    关于char, wchar_t, TCHAR, _T(),L,宏 _T、TEXT,_TEXT、L
    VS2005、VS2008中的快捷键、组合键大全
    could not be found (are you missing a using directive or an assembly reference?)
    项目任务管理系统
    VSDBCMD
    sqlcmd
    Microsoft® Command Line Utilities 11 for SQL Server®
  • 原文地址:https://www.cnblogs.com/hu-yewen/p/5560545.html
Copyright © 2011-2022 走看看