1. 程式人生 > >數據結構之散列(開放定址法)

數據結構之散列(開放定址法)

測試用例 開放定址法 測試 可能 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

數據結構之散列(開放定址法)