Implemented hashmap deletion with tombstones
This commit is contained in:
parent
44c9833117
commit
f22c7c1a73
3 changed files with 169 additions and 36 deletions
29
examples/hm_del.c
Normal file
29
examples/hm_del.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#include <stdio.h>
|
||||
#define LAZY_IMPL
|
||||
#include "../lazy.h"
|
||||
|
||||
void print_hm_idx(void *hm, size_t k) {
|
||||
typedef Lz_HM(size_t, size_t) HM;
|
||||
HM map = *(HM*)hm;
|
||||
if (lz_hm_exists(map,k)) {
|
||||
printf("hm[%zu] = %zu\n", k, lz_hm_get(map,k));
|
||||
} else {
|
||||
printf("hm[%zu] = <N/A>\n", k);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
Lz_HM(size_t, size_t) hm;
|
||||
lz_hm_init(hm);
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
lz_hm_add(hm, i, 2*i);
|
||||
}
|
||||
|
||||
for (size_t i = 4; i < 12; ++i) {
|
||||
lz_hm_remove(hm, i);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 16; ++i) {
|
||||
print_hm_idx(&hm, i);
|
||||
}
|
||||
}
|
||||
|
|
@ -5,11 +5,12 @@
|
|||
int main() {
|
||||
Lz_HM(size_t,size_t) hm;
|
||||
lz_hm_init(hm);
|
||||
for (size_t i = 0; i < 384; ++i) {
|
||||
size_t cnt = 384;
|
||||
for (size_t i = 0; i < cnt; ++i) {
|
||||
lz_hm_add(hm, i, 2*i);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 384; ++i) {
|
||||
printf("hm[%zu] = %zu\n", i, lz_hm_get(hm,i));
|
||||
for (size_t i = 0; i < cnt; ++i) {
|
||||
printf("hm[%zu] = %zu\n", i, lz_hm_get(hm, i));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
169
lazy.h
169
lazy.h
|
|
@ -20,20 +20,26 @@ typedef struct {
|
|||
} Lz_Slc;
|
||||
#endif
|
||||
|
||||
void lz_trim_left_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_trim_right_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_trim_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_drop_left(Lz_Slc *src, size_t n);
|
||||
void lz_drop_right(Lz_Slc *src, size_t n);
|
||||
void lz_split_slc(Lz_Slc *src, char delim, Lz_Slc *dst);
|
||||
void lz_split_slc_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst);
|
||||
void lz_slc_trim_left_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_slc_trim_right_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_slc_trim_typ(Lz_Slc *src, int (*classfunc)(int));
|
||||
void lz_slc_drop_left(Lz_Slc *src, size_t n);
|
||||
void lz_slc_drop_right(Lz_Slc *src, size_t n);
|
||||
void lz_slc_split(Lz_Slc *src, char delim, Lz_Slc *dst);
|
||||
void lz_slc_split_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst);
|
||||
size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s);
|
||||
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, void *key,
|
||||
void *keys, size_t k_s);
|
||||
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists, void* key, size_t k_s);
|
||||
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, _Bool *tombstones,
|
||||
void *key, void *keys, size_t k_s);
|
||||
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists,
|
||||
_Bool *tombstones, void* key, size_t k_s);
|
||||
Lz_Slc lz_cstr_to_slc(char *dat);
|
||||
char *lz_cstr_dup(const char *s);
|
||||
|
||||
double lz_slc_atof(Lz_Slc *src);
|
||||
int lz_slc_atoi(Lz_Slc *src);
|
||||
long lz_slc_atol(Lz_Slc *src);
|
||||
long long lz_slc_atoll(Lz_Slc *src);
|
||||
|
||||
#ifndef Lz_DA
|
||||
#define Lz_DA(T) struct {T *data; size_t cnt; size_t cap; }
|
||||
#endif
|
||||
|
|
@ -129,6 +135,12 @@ char *lz_cstr_dup(const char *s);
|
|||
typedef Lz_DA(char) Lz_SB;
|
||||
#endif
|
||||
|
||||
double lz_sb_atof(Lz_SB *src);
|
||||
int lz_sb_atoi(Lz_SB *src);
|
||||
long lz_sb_atol(Lz_SB *src);
|
||||
long long lz_sb_atoll(Lz_SB *src);
|
||||
|
||||
|
||||
#ifndef Lz_HM
|
||||
#define Lz_HM(K_t, V_t) struct {\
|
||||
size_t cap;\
|
||||
|
|
@ -138,6 +150,7 @@ typedef Lz_DA(char) Lz_SB;
|
|||
K_t tmpkey;\
|
||||
V_t tmpval;\
|
||||
_Bool *exists;\
|
||||
_Bool *tombstones;\
|
||||
K_t *keys;\
|
||||
V_t *vals;\
|
||||
}
|
||||
|
|
@ -149,21 +162,24 @@ typedef Lz_DA(char) Lz_SB;
|
|||
(hm).cnt = 0;\
|
||||
(hm).keys = malloc((hm).cap*sizeof(*(hm).keys));\
|
||||
(hm).vals = malloc((hm).cap*sizeof(*(hm).vals));\
|
||||
(hm).exists = malloc((hm).cap*sizeof(_Bool));\
|
||||
(hm).exists = calloc((hm).cap,sizeof(_Bool));\
|
||||
(hm).tombstones = calloc((hm).cap,sizeof(_Bool));\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef lz_hm_hash_set
|
||||
#define lz_hm_hash_set(hm, k) (\
|
||||
(hm).tmpkey = k,\
|
||||
lz_hm_hash_void_set((hm).cap, (hm).exists, &(hm).tmpkey, sizeof(*(hm).keys))\
|
||||
lz_hm_hash_void_set((hm).cap, (hm).exists, (hm).tombstones,\
|
||||
&(hm).tmpkey, sizeof(*(hm).keys))\
|
||||
)
|
||||
#endif
|
||||
|
||||
#ifndef lz_hm_hash_get
|
||||
#define lz_hm_hash_get(hm, k) (\
|
||||
(hm).tmpkey = k,\
|
||||
lz_hm_hash_void_get((hm).cap, (hm).exists, &(hm).tmpkey, (hm).keys, sizeof(*(hm).keys))\
|
||||
lz_hm_hash_void_get((hm).cap, (hm).exists, (hm).tombstones,\
|
||||
&(hm).tmpkey, (hm).keys, sizeof(*(hm).keys))\
|
||||
)
|
||||
#endif
|
||||
|
||||
|
|
@ -187,16 +203,21 @@ typedef Lz_DA(char) Lz_SB;
|
|||
void *newkeys = malloc(newcap*sizeof(*(hm).keys));\
|
||||
void *newvals = malloc(newcap*sizeof(*(hm).vals));\
|
||||
_Bool *newexists = calloc(newcap, sizeof(_Bool));\
|
||||
_Bool *newtombstones = calloc(newcap, sizeof(_Bool));\
|
||||
printf("Grow\n");\
|
||||
\
|
||||
for (size_t i = 0; i < (hm).cap; ++i) {\
|
||||
if ((hm).exists[i]) {\
|
||||
size_t newhash = lz_hm_hash_void_set(newcap, newexists,\
|
||||
&(hm).keys[i], sizeof(*(hm).keys));\
|
||||
newtombstones,\
|
||||
&(hm).keys[i],\
|
||||
sizeof(*(hm).keys));\
|
||||
memcpy(newvals + sizeof(*(hm).vals)*newhash,\
|
||||
&(hm).vals[i], sizeof(*(hm).vals));\
|
||||
memcpy(newkeys + sizeof(*(hm).keys)*newhash,\
|
||||
&(hm).keys[i], sizeof(*(hm).keys));\
|
||||
newexists[newhash] = 1;\
|
||||
newtombstones[newhash] = 0;\
|
||||
}\
|
||||
}\
|
||||
free((hm).vals);\
|
||||
|
|
@ -205,6 +226,8 @@ typedef Lz_DA(char) Lz_SB;
|
|||
(hm).keys = newkeys;\
|
||||
free((hm).exists);\
|
||||
(hm).exists = newexists;\
|
||||
free((hm).tombstones);\
|
||||
(hm).tombstones = newtombstones;\
|
||||
(hm).cap = newcap;\
|
||||
} while(0)
|
||||
#endif
|
||||
|
|
@ -216,14 +239,23 @@ typedef Lz_DA(char) Lz_SB;
|
|||
(hm).vals[idx] = v;\
|
||||
++(hm).cnt;\
|
||||
(hm).exists[idx] = 1;\
|
||||
(hm).tombstones[idx] = 0;\
|
||||
if (4*(hm).cnt > 3*(hm).cap) {\
|
||||
lz_hm_grow(hm);\
|
||||
}\
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef LAZY_IMPL
|
||||
#ifndef lz_hm_remove
|
||||
#define lz_hm_remove(hm, k) do {\
|
||||
size_t idx = lz_hm_hash_get(hm,k);\
|
||||
(hm).tombstones[idx] = 1;\
|
||||
(hm).exists[idx] = 0;\
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
#ifdef LAZY_IMPL
|
||||
#undef LAZY_IMPL
|
||||
size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s) {
|
||||
size_t hash = 0;
|
||||
for (size_t i = 0; i < k_s; ++i) {
|
||||
|
|
@ -234,32 +266,35 @@ size_t lz_hm_hash_raw_bytes(size_t cap, void *key, size_t k_s) {
|
|||
return hash % cap;
|
||||
}
|
||||
|
||||
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, void *key,
|
||||
void *keys, size_t k_s) {
|
||||
size_t lz_hm_hash_void_get(size_t cap, _Bool *exists, _Bool *tombstones,
|
||||
void *key, void *keys, size_t k_s) {
|
||||
size_t hash = lz_hm_hash_raw_bytes(cap, key, k_s);
|
||||
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
size_t localhash = (hash + i) % cap;
|
||||
int diff = memcmp(keys+k_s*localhash, key, k_s);
|
||||
if (diff == 0) {
|
||||
size_t tombstone = tombstones[localhash];
|
||||
if (diff == 0 && !tombstone) {
|
||||
return localhash;
|
||||
}
|
||||
|
||||
size_t istaken = exists[localhash];
|
||||
if (!istaken) {
|
||||
if (!istaken && !tombstone) {
|
||||
return (size_t)-1;
|
||||
}
|
||||
}
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists, void* key, size_t k_s) {
|
||||
size_t lz_hm_hash_void_set(size_t cap, _Bool *exists,
|
||||
_Bool *tombstones, void* key, size_t k_s) {
|
||||
size_t hash = lz_hm_hash_raw_bytes(cap, key, k_s);
|
||||
|
||||
for (size_t i = 0; i < cap; ++i) {
|
||||
size_t localhash = (hash + i) % cap;
|
||||
_Bool tombstone = tombstones[localhash];
|
||||
_Bool istaken = exists[localhash];
|
||||
if (!istaken) return localhash;
|
||||
if (!istaken || tombstone) return localhash;
|
||||
}
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
|
@ -274,35 +309,35 @@ char *lz_cstr_dup(const char *s) {
|
|||
memcpy(p, s, n+1);
|
||||
return p;
|
||||
}
|
||||
void lz_drop_left(Lz_Slc *src, size_t n) {
|
||||
void lz_slc_drop_left(Lz_Slc *src, size_t n) {
|
||||
if (src->cnt < n) n = src->cnt;
|
||||
src->data += n;
|
||||
src->cnt -= n;
|
||||
}
|
||||
|
||||
void lz_drop_right(Lz_Slc *src, size_t n) {
|
||||
void lz_slc_drop_right(Lz_Slc *src, size_t n) {
|
||||
if (src->cnt < n) n = src->cnt;
|
||||
src->cnt -= n;
|
||||
}
|
||||
|
||||
void lz_trim_left_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
void lz_slc_trim_left_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
while (classfunc(src->data[0])) {
|
||||
lz_drop_left(src, 1);
|
||||
lz_slc_drop_left(src, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void lz_trim_right_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
void lz_slc_trim_right_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
while (classfunc(src->data[src->cnt-1])) {
|
||||
lz_drop_right(src, 1);
|
||||
lz_slc_drop_right(src, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void lz_trim_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
lz_trim_left_typ(src, classfunc);
|
||||
lz_trim_right_typ(src, classfunc);
|
||||
void lz_slc_trim_typ(Lz_Slc *src, int (*classfunc)(int)) {
|
||||
lz_slc_trim_left_typ(src, classfunc);
|
||||
lz_slc_trim_right_typ(src, classfunc);
|
||||
}
|
||||
|
||||
void lz_split_slc(Lz_Slc *src, char delim, Lz_Slc *dst) {
|
||||
void lz_slc_split(Lz_Slc *src, char delim, Lz_Slc *dst) {
|
||||
size_t i = 0;
|
||||
while (i < src->cnt && src->data[i] != delim) {
|
||||
++i;
|
||||
|
|
@ -317,7 +352,7 @@ void lz_split_slc(Lz_Slc *src, char delim, Lz_Slc *dst) {
|
|||
}
|
||||
}
|
||||
|
||||
void lz_split_slc_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst) {
|
||||
void lz_slc_split_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst) {
|
||||
size_t i = 0;
|
||||
while (i < src->cnt && !classfunc(src->data[i])) {
|
||||
++i;
|
||||
|
|
@ -330,7 +365,7 @@ void lz_split_slc_typ(Lz_Slc *src, int (*classfunc)(int), Lz_Slc *dst) {
|
|||
} else {
|
||||
src->cnt = 0;
|
||||
}
|
||||
lz_trim_left_typ(src, classfunc);
|
||||
lz_slc_trim_left_typ(src, classfunc);
|
||||
}
|
||||
|
||||
Lz_SB lz_sb_from_cstr(const char *dat) {
|
||||
|
|
@ -348,4 +383,72 @@ Lz_Slc lz_cstr_to_slc(char *dat) {
|
|||
out.cnt = strlen(dat);
|
||||
return out;
|
||||
}
|
||||
|
||||
double lz_slc_atof(Lz_Slc *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
double x = atof(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
int lz_slc_atoi(Lz_Slc *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atoi(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
long lz_slc_atol(Lz_Slc *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atol(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
long long lz_slc_atoll(Lz_Slc *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atoll(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double lz_sb_atof(Lz_SB *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
double x = atof(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
int lz_sb_atoi(Lz_SB *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atoi(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
long lz_sb_atol(Lz_SB *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atol(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
long long lz_sb_atoll(Lz_SB *src) {
|
||||
char *cstr = malloc(src->cnt+1);
|
||||
memcpy(cstr, src->data, src->cnt);
|
||||
cstr[src->cnt] = 0;
|
||||
int x = atoll(cstr);
|
||||
free(cstr);
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue