Add list length member and simple statistics.

This commit is contained in:
Darko 2015-03-21 13:57:45 +01:00
parent 526617cfc9
commit 4f055d709e
5 changed files with 154 additions and 18 deletions

12
main.c
View file

@ -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;

View file

@ -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);
}

View file

@ -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
View file

@ -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
View file

@ -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, ...);