散列表(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 }
