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 }