Add list length member and simple statistics.
This commit is contained in:
parent
526617cfc9
commit
4f055d709e
5 changed files with 154 additions and 18 deletions
12
main.c
12
main.c
|
@ -76,6 +76,7 @@ int main(int argc, char **argv)
|
|||
key = random() % KEYCNT;
|
||||
keys[i] = key;
|
||||
res = sl_add(&sl, key, NULL);
|
||||
sl_stat_print(&sl);
|
||||
switch(res) {
|
||||
case SL_ADD_NEW:
|
||||
++cntnew;
|
||||
|
@ -88,7 +89,8 @@ int main(int argc, char **argv)
|
|||
break;
|
||||
}
|
||||
}
|
||||
printf("added %d new keys, %d same keys\n", cntnew, cntsame);
|
||||
printf("added %d new keys, %d same keys, list len: %lu\n",
|
||||
cntnew, cntsame, sl.len);
|
||||
dodebug = 1;
|
||||
sl_print(&sl);
|
||||
dodebug = 0;
|
||||
|
@ -96,6 +98,7 @@ int main(int argc, char **argv)
|
|||
for (i = 0; i < KEYCNT; ++i) {
|
||||
key = keys[i];
|
||||
x = sl_find(&sl, key);
|
||||
sl_stat_print(&sl);
|
||||
if (!x) {
|
||||
failed = 1;
|
||||
break;
|
||||
|
@ -108,6 +111,7 @@ int main(int argc, char **argv)
|
|||
for (i = 0; i < KEYCNT; ++i) {
|
||||
key = keys[i];
|
||||
res = sl_remove(&sl, key);
|
||||
sl_stat_print(&sl);
|
||||
switch (res) {
|
||||
case 0:
|
||||
++cntsame;
|
||||
|
@ -126,7 +130,11 @@ int main(int argc, char **argv)
|
|||
if (failed) {
|
||||
fatal("remove failed, report bug\n");
|
||||
}
|
||||
printf("removed %d new keys, %d same keys\n", cntnew, cntsame);
|
||||
dodebug = 1;
|
||||
sl_print(&sl);
|
||||
dodebug = 0;
|
||||
printf("removed %d keys, %d same keys, list len: %lu\n",
|
||||
cntnew, cntsame, sl.len);
|
||||
sl_free(&sl);
|
||||
|
||||
return 0;
|
||||
|
|
104
skiplist.c
104
skiplist.c
|
@ -27,6 +27,21 @@ void sl_init(slist *sl)
|
|||
sl->bottomright = y;
|
||||
|
||||
sl->maxlevel = 0;
|
||||
sl->len = 2; /* -INF and +INF */
|
||||
|
||||
sl->stat.srchcnt = 0;
|
||||
sl->stat.rmcnt = 0;
|
||||
sl->stat.addcnt = 0;
|
||||
sl->stat.srchnum = 0;
|
||||
sl->stat.rmnum = 0;
|
||||
sl->stat.addnum = 0;
|
||||
sl->stat.maxlen = sl->len;
|
||||
sl->stat.currsrch = 0;
|
||||
sl->stat.currrm = 0;
|
||||
sl->stat.curradd = 0;
|
||||
sl->stat.srchcntmax = 0;
|
||||
sl->stat.rmcntmax = 0;
|
||||
sl->stat.addcntmax = 0;
|
||||
}
|
||||
|
||||
void _sl_add_level(slist *sl)
|
||||
|
@ -68,11 +83,11 @@ void sl_free(slist *sl)
|
|||
void _print_key(int key)
|
||||
{
|
||||
if (key == KEY_INF_MIN) {
|
||||
debug("-INF -> ");
|
||||
print("-INF -> ");
|
||||
} else if (key == KEY_INF_MAX) {
|
||||
debug("+INF -> ");
|
||||
print("+INF -> ");
|
||||
} else {
|
||||
debug("%d -> ", key);
|
||||
print("%d -> ", key);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,9 +96,9 @@ void _sl_println()
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 79; ++i) {
|
||||
debug("-");
|
||||
print("-");
|
||||
}
|
||||
debug("\n");
|
||||
print("\n");
|
||||
}
|
||||
|
||||
void sl_print(const slist *sl)
|
||||
|
@ -93,20 +108,21 @@ void sl_print(const slist *sl)
|
|||
int level = sl->maxlevel;
|
||||
|
||||
_sl_println();
|
||||
print("from top to bottom:\n");
|
||||
for (foo = sl->topleft; foo != NULL; foo = foo->below, --level) {
|
||||
debug("level %d: ", level);
|
||||
print("level %d: ", level);
|
||||
for (x = foo; x != NULL; x = x->next) {
|
||||
_print_key(x->key);
|
||||
}
|
||||
debug("\n");
|
||||
print("\n");
|
||||
}
|
||||
_sl_println();
|
||||
debug("from below to above:\n");
|
||||
print("from below to above:\n");
|
||||
for (foo = sl->bottomleft; foo != NULL; foo = foo->next) {
|
||||
for (x = foo; x != NULL; x = x->above) {
|
||||
_print_key(x->key);
|
||||
}
|
||||
debug("\n");
|
||||
print("\n");
|
||||
}
|
||||
_sl_println();
|
||||
}
|
||||
|
@ -201,10 +217,15 @@ int sl_add(slist *sl, int key, void *data)
|
|||
bzero(update, sizeof(sl_node *) * (sl->maxlevel + 1));
|
||||
level = sl->maxlevel;
|
||||
|
||||
++sl->stat.addnum;
|
||||
foo = sl->topleft;
|
||||
++sl->stat.addcnt;
|
||||
sl->stat.curradd = 1;
|
||||
while (1) {
|
||||
while (key >= foo->next->key) {
|
||||
foo = foo->next;
|
||||
++sl->stat.addcnt;
|
||||
++sl->stat.curradd;
|
||||
}
|
||||
if (foo->below == NULL) {
|
||||
break;
|
||||
|
@ -214,7 +235,10 @@ int sl_add(slist *sl, int key, void *data)
|
|||
*/
|
||||
update[level--] = foo;
|
||||
foo = foo->below;
|
||||
++sl->stat.addcnt;
|
||||
++sl->stat.curradd;
|
||||
}
|
||||
sl->stat.addcntmax = max(sl->stat.addcntmax, sl->stat.curradd);
|
||||
update[level] = foo;
|
||||
|
||||
debug("search finished at key: %d\n", foo->key);
|
||||
|
@ -248,6 +272,10 @@ int sl_add(slist *sl, int key, void *data)
|
|||
}
|
||||
++level;
|
||||
}
|
||||
++sl->len;
|
||||
if (sl->len > sl->stat.maxlen) {
|
||||
sl->stat.maxlen = sl->len;
|
||||
}
|
||||
}
|
||||
_sl_clean_top(sl);
|
||||
free(update);
|
||||
|
@ -268,15 +296,23 @@ sl_node *sl_find(slist *sl, int key)
|
|||
sl_node *foo;
|
||||
|
||||
foo = sl->topleft;
|
||||
sl->stat.currsrch = 1;
|
||||
++sl->stat.srchcnt;
|
||||
++sl->stat.srchnum;
|
||||
while (1) {
|
||||
while (key >= foo->next->key) {
|
||||
foo = foo->next;
|
||||
++sl->stat.srchcnt;
|
||||
++sl->stat.currsrch;
|
||||
}
|
||||
if (foo->below == NULL) {
|
||||
break;
|
||||
}
|
||||
foo = foo->below;
|
||||
++sl->stat.srchcnt;
|
||||
++sl->stat.currsrch;
|
||||
}
|
||||
sl->stat.srchcntmax = max(sl->stat.srchcntmax, sl->stat.currsrch);
|
||||
|
||||
if (foo->key != key) {
|
||||
foo = NULL;
|
||||
|
@ -296,15 +332,23 @@ int sl_remove(slist *sl, int key)
|
|||
int result;
|
||||
|
||||
foo = sl->topleft;
|
||||
sl->stat.currrm = 1;
|
||||
++sl->stat.rmcnt;
|
||||
++sl->stat.rmnum;
|
||||
while (1) {
|
||||
while (key >= foo->next->key) {
|
||||
foo = foo->next;
|
||||
++sl->stat.rmcnt;
|
||||
++sl->stat.currrm;
|
||||
}
|
||||
if (foo->below == NULL) {
|
||||
break;
|
||||
}
|
||||
foo = foo->below;
|
||||
++sl->stat.rmcnt;
|
||||
++sl->stat.currrm;
|
||||
}
|
||||
sl->stat.rmcntmax = max(sl->stat.rmcntmax, sl->stat.currrm);
|
||||
|
||||
if (foo->key == key) {
|
||||
result = 1;
|
||||
|
@ -317,6 +361,7 @@ int sl_remove(slist *sl, int key)
|
|||
foo = foo->above;
|
||||
free(x);
|
||||
}
|
||||
--sl->len;
|
||||
|
||||
_sl_clean_top(sl);
|
||||
} else {
|
||||
|
@ -325,3 +370,44 @@ int sl_remove(slist *sl, int key)
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
void sl_stat_print(const slist *sl)
|
||||
{
|
||||
size_t avgsrch;
|
||||
size_t avgadd;
|
||||
size_t avgrm;
|
||||
|
||||
_sl_println();
|
||||
print("skiplist statistics:\n");
|
||||
print("current len: %lu\n", sl->len);
|
||||
|
||||
print("search count: %lu\n", sl->stat.srchcnt);
|
||||
print("add count: %lu\n", sl->stat.addcnt);
|
||||
print("remove count: %lu\n", sl->stat.rmcnt);
|
||||
|
||||
print("search num: %lu\n", sl->stat.srchnum);
|
||||
print("add num: %lu\n", sl->stat.addnum);
|
||||
print("remove num: %lu\n", sl->stat.rmnum);
|
||||
|
||||
print("current search count: %lu\n", sl->stat.currsrch);
|
||||
print("current add count: %lu\n", sl->stat.curradd);
|
||||
print("current remove count: %lu\n", sl->stat.currrm);
|
||||
|
||||
if (sl->stat.srchnum != 0) {
|
||||
avgsrch = sl->stat.srchcnt / sl->stat.srchnum;
|
||||
print("average search count: %lu\n", avgsrch);
|
||||
}
|
||||
if (sl->stat.addnum != 0) {
|
||||
avgadd = sl->stat.addcnt / sl->stat.addnum;
|
||||
print("average add count: %lu\n", avgadd);
|
||||
}
|
||||
if (sl->stat.rmnum != 0) {
|
||||
avgrm = sl->stat.rmcnt / sl->stat.rmnum;
|
||||
print("average remove count: %lu\n", avgrm);
|
||||
}
|
||||
|
||||
print("maxlen: %lu\n", sl->stat.maxlen);
|
||||
print("max search count: %lu\n", sl->stat.srchcntmax);
|
||||
print("max add count: %lu\n", sl->stat.addcntmax);
|
||||
print("max remove count: %lu\n", sl->stat.rmcntmax);
|
||||
}
|
||||
|
|
31
skiplist.h
31
skiplist.h
|
@ -4,6 +4,7 @@
|
|||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define KEY_INF_MIN INT_MIN /* -INFINITY */
|
||||
#define KEY_INF_MAX INT_MAX /* +INFINITY */
|
||||
|
@ -12,6 +13,8 @@
|
|||
#define SL_ADD_SAME 0 /* added existing key */
|
||||
#define SL_ADD_INV -1 /* added invalid key (+-INFINITY) */
|
||||
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
/* skip list node */
|
||||
typedef struct skiplist_node {
|
||||
int key;
|
||||
|
@ -22,6 +25,27 @@ typedef struct skiplist_node {
|
|||
struct skiplist_node *above;
|
||||
} sl_node;
|
||||
|
||||
/* skiplist statistics */
|
||||
typedef struct skiplist_stats {
|
||||
size_t srchcnt; /* count nodes visited while searching */
|
||||
size_t rmcnt; /* count nodes visited while removing */
|
||||
size_t addcnt; /* count nodes visited while adding */
|
||||
|
||||
size_t srchnum; /* number of searches */
|
||||
size_t rmnum; /* number of removals */
|
||||
size_t addnum; /* number of additions */
|
||||
|
||||
size_t maxlen; /* maximum list len */
|
||||
|
||||
size_t currsrch; /* nodes visited for current search */
|
||||
size_t currrm; /* nodes visited for current search */
|
||||
size_t curradd; /* nodes visited for current search */
|
||||
|
||||
size_t srchcntmax; /* max nodes count visited while searching */
|
||||
size_t rmcntmax; /* max nodes count visited while removing */
|
||||
size_t addcntmax; /* max nodes count visited while adding */
|
||||
} slstat;
|
||||
|
||||
/* skiplist object */
|
||||
typedef struct skiplist {
|
||||
sl_node *topleft;
|
||||
|
@ -29,6 +53,8 @@ typedef struct skiplist {
|
|||
sl_node *topright;
|
||||
sl_node *bottomright;
|
||||
int maxlevel;
|
||||
size_t len;
|
||||
slstat stat;
|
||||
} slist;
|
||||
|
||||
/*
|
||||
|
@ -58,6 +84,9 @@ sl_node *sl_find(slist *sl, int key);
|
|||
* If key is found and removed return 1, otherwise 0.
|
||||
*/
|
||||
int sl_remove(slist *sl, int key);
|
||||
|
||||
/*
|
||||
* Print current statistics.
|
||||
*/
|
||||
void sl_stat_print(const slist *sl);
|
||||
#endif
|
||||
|
||||
|
|
21
x.c
21
x.c
|
@ -2,14 +2,14 @@
|
|||
|
||||
extern int dodebug;
|
||||
|
||||
static void _log_stderr(const char *fmt, va_list ap)
|
||||
static void _log_stderr(FILE *f, const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[MAXLINE];
|
||||
|
||||
vsnprintf(buf, MAXLINE-1, fmt, ap);
|
||||
fflush(stdout);
|
||||
fputs(buf, stderr);
|
||||
fflush(stderr);
|
||||
fflush(f);
|
||||
fputs(buf, f);
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
void fatal(const char *fmt, ...)
|
||||
|
@ -17,7 +17,7 @@ void fatal(const char *fmt, ...)
|
|||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_log_stderr(fmt, ap);
|
||||
_log_stderr(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -28,11 +28,20 @@ void debug(const char *fmt, ...)
|
|||
|
||||
if (dodebug) {
|
||||
va_start(ap, fmt);
|
||||
_log_stderr(fmt, ap);
|
||||
_log_stderr(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void print(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
_log_stderr(stdout, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void *xmalloc(size_t size)
|
||||
{
|
||||
void *foo = malloc(size);
|
||||
|
|
4
x.h
4
x.h
|
@ -16,3 +16,7 @@ void *xmalloc(size_t size);
|
|||
* Print debug message if debug is enabled.
|
||||
*/
|
||||
void debug(const char *fmt, ...);
|
||||
/*
|
||||
* Print to stdout.
|
||||
*/
|
||||
void print(const char *fmt, ...);
|
||||
|
|
Loading…
Reference in a new issue