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 }