数据结构之散列(开放定址法)

Posted kaiqiang123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之散列(开放定址法)相关的知识,希望对你有一定的参考价值。

 1 // OHash
 2 // 关键字:int
 3 // Hash函数:hash(X) = X mod TableSize
 4 // 冲突解决方法:开放定址法。Index(X, i) = (hash(X) + f(i)) mod TableSize, f(0) = 0
 5 // 其中f(i)为:
 6 // 1. 线性, f(i) = i
 7 // 2. 平方, f(i) = i ^ 2
 8 // 3. 双散列, f(i) = i * hash2(X), hash2(X, R) = R - (X mod R), R = 7
 9 
10 // 前缀:OHash
11 
12 #ifndef _OHASH_H
13 #define _OHASH_H
14 
15 #define OHASH_DEFAULT_CAPACITY 10
16 
17 // 已被插入值, 空, 惰性删除 
18 enum KindOfEntry { Legitimate, Empty, Deleted };       
19 
20 typedef unsigned int Rank;       // 数组,寻秩访问
21 typedef int OHash_T;
22 typedef struct {
23     OHash_T Elem;
24     enum KindOfEntry Info;  // 当前节点状态信息
25 }OHashEntry;
26 typedef struct {
27     int TableSize;
28     OHashEntry *TheEntrys;      // OHashEntry数组
29 } OHashNode;
30 typedef OHashNode *OHash;
31 
32 
33 // 创建,销毁
34 OHash OHash_Create( int TableSize );
35 void OHash_Destroy( OHash *Phash );
36 
37 // 增(改) 删 查
38 // 向H中插入E,若E已经存在,则什么也不做
39 void OHash_Insert( OHash H, OHash_T E );
40 // 从H中惰性删除E,若E不存在,则什么也不做
41 void OHash_Delete( OHash H, OHash_T E );
42 // 查找E在H中的位置(下标),若E不存在,返回-1。
43 // 即使其值为E,若状态为Deleted,仍返回-1
44 Rank OHash_Find( OHash H, OHash_T E );
45 // test
46 void Test_OHashPrint( OHash H );
47 
48 #endif /* _OHASH_H */
技术分享图片
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include "ohash.h"
  4 
  5 // hash(X) = X mod TableSize
  6 static int hash(OHash_T X, int TableSize)
  7 {
  8     return (unsigned int)X % TableSize;
  9 }
 10 
 11 // hash2(X, R) = R - (X mod R)
 12 static int hash2(OHash_T X, int R)
 13 {
 14     return R - (unsigned int)X % R;
 15 }
 16 
 17 // 冲突处理,其中f(0) = 0
 18 // 1. 线性, f(i) = i
 19 // 2. 平方, f(i) = i ^ 2
 20 // 3. 双散列, f(i) = i * hash2(X, R)
 21 static int f(OHash_T X, int I)
 22 {
 23     //return I;               // 线性
 24     return I * I;           // 平方
 25     //return I * hash2(X, 7); // 双散列 测试R = 7
 26 }
 27 
 28 // 将X映射到下标
 29 // Index(X, i) = (hash(X) + f(i)) mod TableSize, f(0) = 0
 30 static Rank Index(OHash_T X, int I, int TableSize)
 31 {
 32     return (hash(X, TableSize) + f(X, I)) % TableSize;
 33 }
 34 
 35 // 创建 销毁
 36 OHash OHash_Create(int TableSize)
 37 {
 38     if(TableSize < OHASH_DEFAULT_CAPACITY) {
 39         TableSize = OHASH_DEFAULT_CAPACITY;
 40     }
 41     OHash hash = (OHash)malloc(sizeof(OHashNode));
 42     if(hash == NULL) {
 43         printf("Out of space!!");
 44         return NULL;
 45     }
 46     hash->TableSize = TableSize;
 47     hash->TheEntrys = (OHashEntry *)malloc(sizeof(OHashEntry) * hash->TableSize);
 48     if(hash->TheEntrys == NULL) {
 49         printf("Out of space!!");
 50         free(hash);
 51         return NULL;
 52     }
 53     
 54     // 将TheEntrys数组中的InFo设为 Empty
 55     for(int i = 0; i < hash->TableSize; i++) {
 56         hash->TheEntrys[i].Info = Empty;
 57     }
 58     
 59     return hash;
 60 }
 61 
 62 void OHash_Destroy(OHash *Phash)
 63 {
 64     if(Phash != NULL && *Phash != NULL) {
 65         OHash hash = *Phash;
 66         free(hash->TheEntrys);
 67         free(hash);
 68         *Phash = NULL;
 69     }
 70 }
 71 
 72 // 增(改) 删 查
 73 // 向H中插入E,若E已经存在,则什么也不做
 74 void OHash_Insert( OHash H, OHash_T E)
 75 {
 76     if(H == NULL) return ;
 77     int i = 0;
 78     Rank index = 0;
 79     printf("Insert Elem %d: ", E);
 80     while(1) {
 81         index = Index(E, i, H->TableSize);
 82         printf("%d, ", index);
 83         // 两个因素: Info(Legitimate, Empty, Deleted), Elem is E(Y, N)。共 3 * 2 = 6种可能
 84         // 列表如下:
 85         // Elem is E \ Info     Le          Em      De
 86         //          Y           插入        插入    插入
 87         //          N           下一个位置  插入    插入
 88         
 89         // 注:此处测试用例
 90         // 1. Add V, Add ..., Add V
 91         // 2. Add V, Delete V, Add V
 92         if( H->TheEntrys[ index ].Elem != E && H->TheEntrys[ index ].Info == Legitimate )
 93         {
 94             i++;
 95         } else {    // 插入
 96             H->TheEntrys[ index ].Elem = E;
 97             H->TheEntrys[ index ].Info = Legitimate;
 98             break;
 99         }
100     }
101     printf("\n");
102 }
103 
104 // 从H中惰性删除E,若E不存在,则什么也不做
105 void OHash_Delete(OHash H, OHash_T E)
106 {
107     if(H == NULL) return ;
108     
109     Rank index = OHash_Find(H, E);
110     if( index != -1 ) {
111         H->TheEntrys[ index ].Info = Deleted;
112         // H->TheEntrys[ index ].Info = Empty; // 如非惰性删除,将会影响之后的查找
113     }
114 }
115 
116 // 查找E在H中的位置(下标),若E不存在,返回-1。
117 // 即使其值为E,若状态为Deleted,仍返回-1
118 Rank OHash_Find(OHash H, OHash_T E)
119 {
120     if(H == NULL) return -1;
121     int index = 0, i = 0;
122     while(1) {
123         // 两个因素: Info(Legitimate, Empty, Deleted), Elem is E(Y, N)。共 3 * 2 = 6种可能
124         // 列表如下:
125         // Elem is E \ Info     Le          Em      De
126         //          Y           index       -1      -1
127         //          N           下一个位置  -1      下一个位置
128         
129         // 测试用例:
130         // 1. Add V, Delete V, Find V
131         index = Index(E, i, H->TableSize);
132         if( H->TheEntrys[ index ].Info == Empty ) {
133             return -1;
134         } else {
135             if ( H->TheEntrys[ index ].Elem != E ) {
136                 i++;
137             } else {
138                 if( H->TheEntrys[ index ].Info == Legitimate ) {
139                     return index;
140                 } else if( H->TheEntrys[ index ].Info == Deleted ) {
141                     return -1;
142                 }
143             }
144         }
145     }
146 }
147 
148 // test
149 void Test_OHashPrint( OHash H )
150 {
151     if(H == NULL) {
152         printf("OHash is NULL.\n");
153     }
154     for(int i = 0; i < H->TableSize; i++) {
155         if (H->TheEntrys[i].Info == Empty ) {
156             printf("--E ");
157         } else if(H->TheEntrys[i].Info == Deleted) {
158             printf("%dD ", H->TheEntrys[i].Elem);
159         } else {
160             printf("%dL ", H->TheEntrys[i].Elem);
161         }
162     }
163     printf("\n");
164 }
ohash.c

 

以上是关于数据结构之散列(开放定址法)的主要内容,如果未能解决你的问题,请参考以下文章

散列表的开放定址法以及再散列法(C语言)

散列——排解冲突 开放定址法(上)

hash算法解决冲突的方案

散列表解决冲突的方式

数据结构—— 散列查找:冲突处理方法

数据结构代码索引