由於C語言中缺乏像C++中的數據容器,所以用C語言自己對hashtable做了一個前期的原理分析及函數定義,以備自己以後查用。字符串的hash處理採用lua源碼中的luaS_hash函數。
hash數據存儲模塊:(只支持一對一的table結構,如果兩個key值一模一樣則更新表中數據)
hash數據結構:struct hash_value {
union{
uint32_t k_num;
char k_char[32]; //最大支持32個字節的key值長度
}key;
void * data; //數據存儲位置
struct hash_value *next; //同一個hash值的數據存儲鏈表
};
typedef struct hash_tab {
struct hash_value ** hash;
uint32_t nuse; //hashtab中已插入的數據條數
uint32_t size; //當前hashtab的大小。
}hash_tab;
通過採用key-value的方式,key支持int,string類型數據,value爲void*類型。hash函數採用luaS_hash函數原型。
提供創建: hash_create(hash_tab *tab, uint32_t size)
修改tab大小:hash_resize(hash_tab *tab, uint32_t newsize)
插入: hash_insert(hash_tab *tab, char *key, void *data)
刪除: hash_remove(hash_tab *tab, char *key, void *data)
查找: hash_value(hash_tab *tab, char *key)
清除: hash_destroy(hash_tab *tab)
擴展接口:(支持插入重複key值的數據,用來實現key值一對多的hashtable)
插入: hash_mult_insert(hash_tab *tab, char *key, void *data)
刪除: hash_remove(hash_tab *tab, char *key, void *data)
查找: hash_values(hash_tab *tab, char *key)
hash表實現原理:
1,初始化一個固定大小的hashtable。例如1024大小。
2,當有一個數據插入進來時,調用luaS_hash計算作爲key值的字符串的hash值。
3,將計算出來的hash值對整個table大小取模,然後將數據存儲到取模後table中對應位置的數據鏈表裏面。
4,如果已插入的數據條數已經達到當前table的大小,則將table的大小翻一倍。將table中的所有hash節點清空。
5,重新計算以前table中的所有數據的hash值,並重新存儲到table表的相應位置。修改table表的大小。
hash表數據查找:
1,將傳入的key值調用luaS_hash計算對應的hash值,
2,將hash值取模得到對應的table表位置,然後循環數據鏈表中的數據對key值進行比較。取出匹配到的數據指針。
備註:如果是int型的key值,可以不做luaS_hash處理,直接對key值進行取模及之後的數據存取操作。