哈希表(Hash table) [散列表] C語言簡單實現


  散列表(Hash table,也叫哈希表),是根據關鍵碼值(Key value)而直接進行訪問的數據結構。也就是說,它通過把關鍵碼值映射到表中一個位置來訪問記錄,以加快查找的速度。這個映射函數叫做散列函數,存放記錄的數組叫做散列表

                                                                                                  ------摘自百度百科

填充因子定義:

  α=表中填充的元素數/哈希表的長度

hash函數計算方式:

1.直接尋址法

2.數字分析法

3.平方取中法

4.折疊法

5.隨機數法

6.除留余數法

7.斐波那契數列

以上方法詳情自行百度,這里不再贅述。

 

哈希表解決沖突有兩種方式:

1.開放地址法 : hi=(h(key)+di)%m ,1<=i<=m-1,di為增量序列,m為表長增量序列, di有不同方法生成 。 盡量填滿每一個hash數組位,所以hash表長度>= 實際插入填充數量   即填充因子至少為1

2.鏈地址法:  把重復的hash值元素放在一個鏈表下。一般不會超過hash表長度,但是為了避免鏈表過長,當填充因子為7/10 時候,hash表大小擴種兩倍

 

下面是C語言實現例子。hash函數主要采用 折疊法+除留余數法,解決沖突采用鏈地址法,暫時未添加自動擴充hash表長度。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 
  5 // hash表默認長度
  6 #define HASH_TABLE_SIZE 16
  7 
  8 // hash表元素鏈表節點
  9 typedef struct __node{
 10     char *key;
 11     char *value;
 12     struct __node *next;
 13 }NODE, *PNODE, **PPNODE;
 14 
 15 // hash表結構
 16 typedef struct __hash_table{
 17     PPNODE table;
 18     unsigned total; // 總空間
 19     unsigned size;  // 已用空間
 20 }HASH_TABLE, *PHASH_TABLE;
 21 
 22 // 創建hash表中元素節點
 23 PNODE create_node(const char* key, const char *value)
 24 {
 25     PNODE pnode = (PNODE)malloc(sizeof(NODE));
 26     if(NULL == pnode) return NULL;
 27 
 28     pnode->next = NULL;
 29     if (NULL != key)
 30     {
 31         unsigned len = strlen(key) + 1;
 32         pnode->key = (char*)malloc(len);
 33         memcpy(pnode->key, key, len);
 34     }
 35 
 36     if (NULL != value)
 37     {
 38         unsigned len = strlen(value) + 1;
 39         pnode->value = (char*)malloc(len);
 40         memcpy(pnode->value, value, len);
 41     }
 42     return pnode;
 43 }
 44 
 45 // 創建hash表
 46 PHASH_TABLE create_hash_table(unsigned size)
 47 {
 48     if(size < 1) return NULL;
 49 
 50     PPNODE ppNodeTable = (PPNODE)malloc(sizeof(PNODE) * size);
 51     if (NULL == ppNodeTable) return NULL;
 52 
 53     for (unsigned i = 0; i < size; i++)
 54     {
 55         ppNodeTable[i] = NULL;
 56     }
 57     PHASH_TABLE pHashTable = (PHASH_TABLE)malloc(sizeof(HASH_TABLE));
 58     if(NULL == pHashTable) return NULL;
 59     pHashTable->table = ppNodeTable;
 60     pHashTable->total = size;
 61     pHashTable->size = 0;
 62     return pHashTable;
 63 }
 64 
 65 // hash函數 對疊法+除留余數法
 66 unsigned hash(const char* key, unsigned hash_size)
 67 {
 68     unsigned int h=0;
 69     for( ; *key != '\0'; ++key)
 70         h = *key + h * 31;
 71     return h%hash_size;
 72 }
 73 
 74 // 從hash表中獲取key對應的value
 75 const char* get_hash_value(PHASH_TABLE pHashTable, const char* key)
 76 {
 77     if(NULL == key) return NULL;
 78 
 79     unsigned index = hash(key, pHashTable->total);
 80     PNODE pnode = pHashTable->table[index];
 81     if(NULL == pnode) return NULL;
 82 
 83     do
 84     {
 85         if(strcmp(pnode->key, key) == 0)
 86         {
 87             return pnode->value;
 88         }
 89 
 90         pnode = pnode->next;
 91     }while (pnode != NULL);    
 92 }
 93 
 94 // 插入hash表
 95 int insert_hash(PHASH_TABLE pHashTable ,const char *key, const char *value)
 96 {
 97     if(NULL == key) return 0;
 98     // 剩余空間不足
 99     if(pHashTable->size == pHashTable->total) return -1;
100 
101     if(get_hash_value(pHashTable, key) != NULL) return -1;
102 
103     
104     PNODE pnode = create_node(key, value);
105     if(NULL == pnode) return 0;
106 
107     unsigned index = hash(key,pHashTable->total);
108     if(NULL == pHashTable->table[index])
109     {
110         pHashTable->table[index] = pnode;
111         ++ pHashTable->size;
112     } else {
113         pnode->next = pHashTable->table[index];
114         pHashTable->table[index] = pnode;
115     }
116 
117     return index;
118 }
119 
120 // 釋放hash表
121 void free_hash_table(PHASH_TABLE pHashTable)
122 {
123     if(NULL == pHashTable || pHashTable->size == 0) return;
124 
125     PNODE pnode = NULL;
126     for (unsigned i = 0; i < pHashTable->total; i++)
127     {
128         pnode = pHashTable->table[i];
129         if(pnode == NULL) continue;
130 
131         PNODE tmp = NULL;
132         while( pnode != NULL)
133         {
134             tmp = pnode;
135             pnode = pnode->next;
136             free(tmp->key);
137             free(tmp->value);
138             free(tmp);
139         }
140         pHashTable->table[i] = NULL;
141         pHashTable->size --;
142         if(pHashTable->size == 0) return;
143     }
144     
145     free(pHashTable->table);
146     free(pHashTable);
147 }
148 
149 // 打印hash表內容
150 void print_hash(PHASH_TABLE pHashTable)
151 {
152     if(NULL == pHashTable || 0 == pHashTable->size) return;
153 
154     for (unsigned i = 0; i < pHashTable->total; i++)
155     {
156         printf("%u ",i);
157         PNODE pnode = pHashTable->table[i];
158         while (pnode != NULL)
159         {
160             if(pnode->value != NULL)
161                 printf("[%s,%s] ",pnode->key, pnode->value);
162             else 
163                 printf("[%s,null] ",pnode->key);
164             pnode = pnode->next;
165         }
166         printf("\n");
167     }
168 }
169 
170 int main(int argc, char *argv[])
171 {
172    PHASH_TABLE pHashTable = create_hash_table(HASH_TABLE_SIZE);
173    insert_hash(pHashTable, "zs","張三");
174    insert_hash(pHashTable, "ls","李四");
175    insert_hash(pHashTable, "we","王二");
176    insert_hash(pHashTable, "mz","麻子");
177    insert_hash(pHashTable, "lb","劉備");
178    insert_hash(pHashTable, "gy","關羽");
179    insert_hash(pHashTable, "zf","張飛");
180    insert_hash(pHashTable, "cc","曹操");
181    insert_hash(pHashTable, "cp","曹丕");
182    insert_hash(pHashTable, "cz","曹植");
183    insert_hash(pHashTable, "cr","曹仁");
184 //    const char* value = get_hash_value(pHashTable,"mz");
185 //    if(value != NULL)
186 //    {
187 //        printf("mz->%s\n",value);
188 //    } else {
189 //        printf("沒有找到zs\n");
190 //    }
191 
192     print_hash(pHashTable);
193     
194     free_hash_table(pHashTable);
195     return 0;
196 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM