开放定址法实现散列表

使用分离链接法实现散列表时需要额外的空间来存储指针,而且需要给新单元动态分配空间,导致算法的速度减慢。开放定址法一次分配表的大小,可以使用线性散列,平方散列,双重散列等等方法,这些方法除了散列函数不相同之外,对于散列表的大小要求也不一样。平方散列需要使表的大小是存储元素的两倍以上,这样总能找到空槽来存放产生冲突的元素。(算法导论上有详细证明。)

下面程序使用的是平方探测散列:

头文件:

 1 /*
 2  * hash.h
 3  *
 4  *  Created on: Dec 12, 2016
 5  *      Author: csf
 6  */
 7 
 8 #ifndef HASH_H_
 9 #define HASH_H_
10 
11 #define MAXTABLESIZE 200
12 #define MINTABLESIZE 1
13 
14 typedef unsigned int Index;
15 typedef Index Position;
16 typedef int ElementType;
17 
18 struct HashTbl;
19 typedef struct HashTbl *HashTable;
20 
21 int IsPrime(int x);
22 int NextPrime(int y);
23 int Hash(ElementType key,int TableSize);
24 HashTable InitializeTable(int TableSize);
25 void DestroyTable(HashTable H);
26 Position Find(ElementType key,HashTable H);
27 void Insert(ElementType key,HashTable H);
28 ElementType Retrieve(Position P,HashTable H);
29 int Delete(ElementType key,HashTable H);
30 HashTable Rehash(HashTable H);
31 
32 #endif /* HASH_H_ */
33 
34 enum KindOfEntry {Legitimate,Empty,Deleted};
35 
36 struct HashEntry
37 {
38     ElementType Element;
39     enum KindOfEntry Info;
40 };
41 
42 typedef struct HashEntry Cell;
43 
44 struct HashTbl
45 {
46     int TableSize;
47     Cell *TheCells;
48 };

源文件:

  1 /*
  2  * hash.c
  3  *
  4  *  Created on: Dec 12, 2016
  5  *      Author: csf
  6  */
  7 
  8 #include "hash.h"
  9 #include "stdio.h"
 10 #include "stdlib.h"
 11 
 12 int IsPrime(int x) //判断素数
 13 {
 14     int i;
 15     for(i=2;i*i<x;i++){
 16         if(x%i==0)
 17             return 0;
 18     }
 19     return 1;
 20 }
 21 
 22 int NextPrime(int y) //查找最邻近素数
 23 {
 24     while(1){
 25     if(IsPrime(y))
 26         return y;
 27     else
 28         y++;
 29     }
 30 }
 31 
 32 int Hash(ElementType key,int TableSize) //简单取余数的散列函数
 33 {
 34     return key%TableSize;
 35 }
 36 
 37 HashTable InitializeTable(int TableSize) //初始化散列表
 38 {
 39     HashTable H;
 40     int i;
 41 
 42     if(TableSize<MINTABLESIZE)
 43         return NULL;
 44 
 45     H=(struct HashTbl*)malloc(sizeof(struct HashTbl));
 46     H->TableSize=NextPrime(TableSize);
 47     if(H==NULL)
 48         return NULL;
 49     H->TheCells=malloc(sizeof(Cell)*H->TableSize);
 50     if(H->TheCells==NULL)
 51         return NULL;
 52     for(i=0;i<H->TableSize;i++)
 53     {
 54         H->TheCells[i].Info=Empty;
 55     }
 56     return H;
 57 }
 58 
 59 Position Find(ElementType key,HashTable H) //查找表内元素,没有该元素返回空槽
 60 {
 61     Position Pos;
 62     int i;
 63 
 64     i=0;
 65     Pos=Hash(key,H->TableSize);
 66     while(H->TheCells[Pos].Info!=Empty && H->TheCells[Pos].Element!=key)//字符串比较用strcmp
 67     {
 68         i+=1;
 69         Pos=Pos+2*i-1;
 70         if(Pos>=H->TableSize)
 71             Pos-=H->TableSize;
 72     }
 73     return Pos;
 74 }
 75 
 76 
 77 void Insert(ElementType key,HashTable H) //插入新元素,元素存在则什么也不做
 78 {
 79     Position Pos;
 80     Pos=Find(key,H);
 81     if(H->TheCells[Pos].Info!=Legitimate)
 82     {
 83         H->TheCells[Pos].Info=Legitimate;
 84         H->TheCells[Pos].Element=key;
 85     }
 86 }
 87 
 88 void DestroyTable(HashTable H) //销毁散列表
 89 {
 90     free(H->TheCells);
 91     free(H);
 92 }
 93 
 94 ElementType Retrieve(Position P,HashTable H) //根据元素位置得到元素值
 95 {
 96     return H->TheCells[P].Element;
 97 }
 98 
 99 int Delete(ElementType key,HashTable H) //删除元素,实际只是把元素标记为deleted
100 {
101     Position TempPos,Pos;
102     int i;
103 
104     i=0;
105     Pos=Hash(key,H->TableSize);
106     TempPos=Pos;
107 
108     if(H->TheCells[Pos].Element!=key)
109     {
110         i+=1;
111         Pos+=2*i-1;
112         if(Pos>H->TableSize)
113             Pos-=H->TableSize;
114         if(TempPos==Pos)
115             return 0;//没有找到该元素,退出避免死循环
116     }
117     H->TheCells[Pos].Info=Deleted;
118     return 1;
119 }
120 
121 HashTable Rehash(HashTable H) //再散列,当填充因子大于0.5或者发生冲突无法找到空槽时使用
122 {
123     int i,OldSize;
124     Cell *OldCells;
125 
126     OldSize=H->TableSize;
127     OldCells=H->TheCells;
128 
129     H=InitializeTable(2*OldSize);
130 
131     for(i=0;i<OldSize;i++)
132     {
133         if(OldCells[i].Info==Legitimate)
134             Insert(OldCells[i].Element,H);
135     }
136     free(OldCells);
137     return H;
138 }
139 
140 void main() //测试用例
141 {
142         Position p;
143 
144         HashTable table=InitializeTable(30);
145 
146 
147         Insert(0,table);
148         Insert(1,table);
149         Insert(81,table);
150         Insert(4,table);
151         Insert(64,table);
152         Insert(25,table);
153         Insert(16,table);
154         Insert(36,table);
155         Insert(9,table);
156         Insert(49,table);
157 
158 
159         p=Find(81,table);
160         printf("%d \n",table->TheCells[p].Element);
161 
162 
163         if(Delete(81,table))
164         {
165             printf("Deleted\n");
166         }
167 
168         if(Delete(100,table))
169         {
170             printf("NoData\n");
171         }
172 
173         DestroyTable(table);
174 }

 

posted @ 2016-12-11 18:27  貔貔貔貔貅  阅读(270)  评论(0编辑  收藏  举报