*optimized hash table algorithm.

This commit is contained in:
paladin-t 2016-01-13 10:56:08 +08:00
parent 686be8e61a
commit 4977143b91
2 changed files with 58 additions and 23 deletions

View File

@ -1,3 +1,6 @@
Jan. 13 2016
Optimized hash table algorithm
Jan. 12 2016 Jan. 12 2016
Improved sub routine by unreference objects which were out of scope Improved sub routine by unreference objects which were out of scope
Fixed a routine evaluation bug when it's stored in a variable Fixed a routine evaluation bug when it's stored in a variable

View File

@ -95,6 +95,9 @@ extern "C" {
# define _MB_VERSION_STRING _STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX) # define _MB_VERSION_STRING _STRINGIZE(_VER_MAJOR._VER_MINOR._VER_REVISION _VER_SUFFIX)
#endif /* _VER_REVISION == 0 */ #endif /* _VER_REVISION == 0 */
/* Define as 1 to create hash table nodes lazily, 0 obligingly */
#define _LAZY_HASH_TABLE 1
/* Define as 1 to treat warning as error, 0 just leave it */ /* Define as 1 to treat warning as error, 0 just leave it */
#define _WARING_AS_ERROR 0 #define _WARING_AS_ERROR 0
@ -1007,11 +1010,13 @@ static int _ht_remove_exist(void* data, void* extra, _ht_node_t* ht);
do { \ do { \
_ls_node_t* __bucket = 0; \ _ls_node_t* __bucket = 0; \
unsigned int __ul = 0; \ unsigned int __ul = 0; \
if((H)->array) { \
for(__ul = 0; __ul < (H)->array_size; ++__ul) { \ for(__ul = 0; __ul < (H)->array_size; ++__ul) { \
__bucket = (H)->array[__ul]; \ __bucket = (H)->array[__ul]; \
if(__bucket) \ if(__bucket) \
_LS_FOREACH(__bucket, O, P, E); \ _LS_FOREACH(__bucket, O, P, E); \
} \ } \
} \
} while(0) } while(0)
/** Memory manipulations */ /** Memory manipulations */
@ -2245,9 +2250,14 @@ _ht_node_t* _ht_create(unsigned int size, _ht_compare cmp, _ht_hash hs, _ls_oper
result->hash = hs; result->hash = hs;
result->array_size = array_size; result->array_size = array_size;
result->count = 0; result->count = 0;
#if _LAZY_HASH_TABLE
mb_unrefvar(ul);
result->array = 0;
#else /* _LAZY_HASH_TABLE */
result->array = (_ls_node_t**)mb_malloc(sizeof(_ls_node_t*) * result->array_size); result->array = (_ls_node_t**)mb_malloc(sizeof(_ls_node_t*) * result->array_size);
for(ul = 0; ul < result->array_size; ++ul) for(ul = 0; ul < result->array_size; ++ul)
result->array[ul] = _ls_create(); result->array[ul] = _ls_create();
#endif /* _LAZY_HASH_TABLE */
return result; return result;
} }
@ -2260,8 +2270,10 @@ _ls_node_t* _ht_find(_ht_node_t* ht, void* key) {
mb_assert(ht && key); mb_assert(ht && key);
hash_code = ht->hash(ht, key); hash_code = ht->hash(ht, key);
if(ht->array && ht->array[hash_code]) {
bucket = ht->array[hash_code]; bucket = ht->array[hash_code];
bucket = bucket->next; bucket = bucket->next;
}
while(bucket) { while(bucket) {
if(ht->compare(bucket->extra, key) == 0) { if(ht->compare(bucket->extra, key) == 0) {
result = bucket; result = bucket;
@ -2278,6 +2290,7 @@ unsigned int _ht_set_or_insert(_ht_node_t* ht, void* key, void* value) {
unsigned int result = 0; unsigned int result = 0;
_ls_node_t* bucket = 0; _ls_node_t* bucket = 0;
unsigned int hash_code = 0; unsigned int hash_code = 0;
unsigned int ul = 0;
mb_assert(ht && key); mb_assert(ht && key);
@ -2287,6 +2300,13 @@ unsigned int _ht_set_or_insert(_ht_node_t* ht, void* key, void* value) {
++result; ++result;
} else { /* Insert */ } else { /* Insert */
hash_code = ht->hash(ht, key); hash_code = ht->hash(ht, key);
if(!ht->array) {
ht->array = (_ls_node_t**)mb_malloc(sizeof(_ls_node_t*) * ht->array_size);
for(ul = 0; ul < ht->array_size; ++ul)
ht->array[ul] = 0;
}
if(!ht->array[hash_code])
ht->array[hash_code] = _ls_create();
bucket = ht->array[hash_code]; bucket = ht->array[hash_code];
bucket = _ls_pushback(bucket, value); bucket = _ls_pushback(bucket, value);
mb_assert(bucket); mb_assert(bucket);
@ -2310,9 +2330,11 @@ unsigned int _ht_remove(_ht_node_t* ht, void* key, _ls_compare cmp) {
bucket = _ht_find(ht, key); bucket = _ht_find(ht, key);
hash_code = ht->hash(ht, key); hash_code = ht->hash(ht, key);
if(ht->array && ht->array[hash_code]) {
bucket = ht->array[hash_code]; bucket = ht->array[hash_code];
result = _ls_try_remove(bucket, key, cmp, ht->free_extra); result = _ls_try_remove(bucket, key, cmp, ht->free_extra);
ht->count -= result; ht->count -= result;
}
return result; return result;
} }
@ -2322,11 +2344,13 @@ unsigned int _ht_foreach(_ht_node_t* ht, _ht_operation op) {
_ls_node_t* bucket = 0; _ls_node_t* bucket = 0;
unsigned int ul = 0; unsigned int ul = 0;
if(ht->array) {
for(ul = 0; ul < ht->array_size; ++ul) { for(ul = 0; ul < ht->array_size; ++ul) {
bucket = ht->array[ul]; bucket = ht->array[ul];
if(bucket) if(bucket)
result += _ls_foreach(bucket, op); result += _ls_foreach(bucket, op);
} }
}
return result; return result;
} }
@ -2340,25 +2364,33 @@ unsigned int _ht_count(_ht_node_t* ht) {
void _ht_clear(_ht_node_t* ht) { void _ht_clear(_ht_node_t* ht) {
unsigned int ul = 0; unsigned int ul = 0;
mb_assert(ht && ht->array); mb_assert(ht);
for(ul = 0; ul < ht->array_size; ++ul) if(ht->array) {
for(ul = 0; ul < ht->array_size; ++ul) {
if(ht->array[ul])
_ls_clear(ht->array[ul]); _ls_clear(ht->array[ul]);
}
ht->count = 0; ht->count = 0;
}
} }
void _ht_destroy(_ht_node_t* ht) { void _ht_destroy(_ht_node_t* ht) {
unsigned int ul = 0; unsigned int ul = 0;
mb_assert(ht && ht->array); mb_assert(ht);
if(ht->array) {
if(ht->free_extra) if(ht->free_extra)
_ht_foreach(ht, ht->free_extra); _ht_foreach(ht, ht->free_extra);
for(ul = 0; ul < ht->array_size; ++ul) for(ul = 0; ul < ht->array_size; ++ul) {
if(ht->array[ul])
_ls_destroy(ht->array[ul]); _ls_destroy(ht->array[ul]);
}
safe_free(ht->array); safe_free(ht->array);
}
safe_free(ht); safe_free(ht);
} }