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 }