分离链接法实现散列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分离链接法实现散列表相关的知识,希望对你有一定的参考价值。
散列表是一种用于查找的数据结构。其基本思想来自于索引,也可以看成是数组的一种扩展。对于一些数据信息,比如说图片文件名,如果我们要查找某张图片,通常将图片名作为关键字进行搜索。这个时候是不可能把图片名直接当成数组下标的,因此可以将图片名关键字通过某个函数映射为某个地址,或地址偏移量。那么每次要查找图片的时候直接输入关键字就能直接计算得出存储地址。其定义
T=h(k)
其中k为关键字,h为映射函数,T为得到的散列表,得到的函数值为地址或地址偏移量。
如果不同关键字通过某函数得到的散列值(地址偏移量)相同,这时就产生了冲突。解决冲突的方法一般有链接法和开放寻址法。
冲突发生后,链接法使冲突元素共享同一个散列值,并且用链表将这些冲突关键字串起来,一旦要查找时,先计算出散列值,然后在对应的链表中进行查找。开放寻址法解决理念则完全不一样。一旦冲突发生,开放寻址法则寻找散列表中没有被填充的槽,直到找到为止。根据散列函数的不同,又有线性散列,二次散列,双重散列等等。
下面是分离链接法的具体实现。参考自《数据结构与算法分析-C语言实现》。
头文件:
1 /* 2 * hash.h 4 * Created on: Dec 8, 2016 5 * Author: csf 6 */ 7 typedef int ElementType; 8 #ifndef HASH_H_ 9 #define HASH_H_ 10 #define MINTABLESIZE 5 11 #define MAXTABLESIZE 100 12 struct ListNode; 13 typedef struct ListNode *Position; 14 struct HashTbl; 15 typedef struct HashTbl *HashTable; 16 17 int IsPrime(int x); 18 int NextPrime(int y); 19 int Hash(ElementType key,int TableSize); 20 HashTable InitializeTable(int TableSize); 21 void DestroyTable(HashTable H); 22 Position Find(ElementType key,HashTable H); 23 void Insert(ElementType key,HashTable H); 24 ElementType Retrieve(Position P); 25 int Delete(ElementType key,HashTable H); 26 #endif /* HASH_H_ */ 27 28 struct ListNode{ 29 ElementType Element; 30 Position Next; 31 }; 32 typedef Position List; 33 struct HashTbl{ 34 int TableSize; 35 List *TheLists; 36 };
源文件:
1 /* 2 * hash.c 4 * Created on: Dec 8, 2016 5 * Author: csf 6 */ 7 #include "hash.h" 8 #include "stdio.h" 9 #include "stdlib.h" 10 int IsPrime(int x) //判断是否为素数 11 { 12 int i; 13 for(i=2;i*i<x;i++){ 14 if(x%i==0) 15 return 0; 16 } 17 return 1; 18 } 19 20 int NextPrime(int y) //寻找最邻近素数 21 { 22 while(1){ 23 if(IsPrime(y)) 24 return y; 25 else 26 y++; 27 } 28 } 29 30 int Hash(ElementType key,int TableSize) //简单散列函数 31 { 32 return key%TableSize; 33 } 34 35 HashTable InitializeTable(int TableSize) //初始化散列表 36 { 37 HashTable H; 38 int i; 39 40 if(TableSize < MINTABLESIZE) 41 return NULL; 42 H=(struct HashTbl*)malloc(sizeof(struct HashTbl)); 43 if(H==NULL) 44 return NULL; 45 H->TableSize=NextPrime(TableSize); 46 H->TheLists=malloc(sizeof(List)*H->TableSize); 47 if(H->TheLists==NULL) 48 return NULL; 49 for(i=0;i<H->TableSize;i++) 50 { 51 H->TheLists[i]=(struct ListNode*)malloc(sizeof(struct ListNode)); 52 if(H->TheLists[i]==NULL) 53 return NULL; 54 else 55 H->TheLists[i]->Next=NULL; 56 } 57 return H; 58 } 59 60 Position Find(ElementType key,HashTable H) //通过关键字查找元素,返回位置 61 { 62 Position P; 63 List L; 64 L=H->TheLists[Hash(key,H->TableSize)]; 65 P=L->Next; 66 while(P!=NULL && P->Element!=key) 67 P=P->Next; 68 return P; 69 } 70 71 void Insert(ElementType key,HashTable H) //插入关键字 72 { 73 Position Pos,NewElement; 74 List L; 75 Pos=Find(key,H); 76 if(Pos==NULL) 77 { 78 NewElement=(struct ListNode*)malloc(sizeof(struct ListNode)); 79 if(NewElement==NULL) 80 exit(0); 81 else 82 { 83 L=H->TheLists[Hash(key,H->TableSize)]; 84 NewElement->Next=L->Next; 85 NewElement->Element=key; 86 L->Next=NewElement; 87 } 88 } 89 } 90 void DestroyTable(HashTable H) //销毁散列表 91 { 92 Position h,p,q; 93 int i; 94 for(i=0;i<H->TableSize;i++) 95 { 96 h=H->TheLists[i]; 97 p=h->Next; 98 while(p) 99 { 100 q=p->Next; 101 if(!q) 102 { 103 free(p); 104 p=NULL; 105 } 106 else 107 { 108 free(p); 109 p=q; 110 } 111 } 112 } 113 } 114 115 int Delete(ElementType key,HashTable H) //删除关键字 116 { 117 Position Pos,L,Temp; 118 Pos=H->TheLists[Hash(key,H->TableSize)]; 119 L=Pos; 120 while(L!=NULL && L->Next!=NULL && L->Next->Element!=key) //单链表删除比较麻烦,需要遍历,双链表则可借助Find 121 { 122 L=L->Next; 123 } 124 if(L==NULL) 125 return 0; 126 else if(L->Next==NULL) 127 free(L); 128 else 129 { 130 Temp=L->Next; 131 L->Next=L->Next->Next; 132 free(Temp); 133 } 134 return 1; 135 } 136 137 138 ElementType Retrieve(Position P) //定位 139 { 140 return P->Element; 141 } 142 143 void main() //测试程序 144 { 145 Position p; 146 147 HashTable table=InitializeTable(10); 148 149 150 Insert(0,table); 151 Insert(1,table); 152 Insert(81,table); 153 Insert(4,table); 154 Insert(64,table); 155 Insert(25,table); 156 Insert(16,table); 157 Insert(36,table); 158 Insert(9,table); 159 Insert(49,table); 160 161 162 p=Find(81,table); 163 if(p==NULL) 164 printf("can‘t find\n"); 165 else 166 printf("find %d \n",p->Element); 167 168 if(Delete(81,table)) 169 { 170 printf("Delete 81\n"); 171 } 172 173 p=Find(81,table); 174 if(p==NULL) 175 printf("can‘t find 81\n"); 176 else 177 printf("find %d \n",p->Element); 178 179 DestroyTable(table); 180 }
以上是关于分离链接法实现散列表的主要内容,如果未能解决你的问题,请参考以下文章