數據結構之散列(開放定址法)
阿新 • • 發佈:2018-03-20
測試用例 開放定址法 測試 可能 print 信息 stat gif try
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
數據結構之散列(開放定址法)