Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

a skip list implementation #102

Closed
wants to merge 5 commits into from

2 participants

@xekoukou
Collaborator

It could replace zlist in the future.

Creating a skipmap is easy to do.

Apostolis Xe... added some commits
Apostolis Xekoukoulotakis a skip-list implementation c7df4f9
Apostolis Xekoukoulotakis added zsklist_destroy, changed makefile 3b0e503
Apostolis Xekoukoulotakis some documentation 5cbf917
Apostolis Xekoukoulotakis turned malloc to zmalloc 223f094
@hintjens
Owner
Apostolis Xekoukoulotakis license aeabfff
@xekoukou
Collaborator

Do you use any indentation program? Also I haven't created the documentation. Do you do it manually?

@hintjens
Owner
@xekoukou xekoukou closed this
@xekoukou
Collaborator

I ll make the changes and then reopen the pull request. Sorry I didnt see the czmq guide about how to make a new class.

@hintjens
Owner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 29, 2012
  1. a skip-list implementation

    Apostolis Xekoukoulotakis authored
  2. added zsklist_destroy, changed makefile

    Apostolis Xekoukoulotakis authored
  3. some documentation

    Apostolis Xekoukoulotakis authored
  4. turned malloc to zmalloc

    Apostolis Xekoukoulotakis authored
  5. license

    Apostolis Xekoukoulotakis authored
This page is out of date. Refresh to see the latest.
View
1  AUTHORS
@@ -11,4 +11,5 @@ Luc Heinrich <luc@honk-honk.com>
William Roberts <bill.c.roberts@gmail.com>
AJ Lewis <aj.lewis@quantum.com>
Philip Kovacs
+Apostolis Xekoukoulotakis <xekoukou@gmail.com>
View
1  include/czmq.h
@@ -53,6 +53,7 @@
#include "zloop.h"
#include "zmsg.h"
#include "zmutex.h"
+#include "zskiplist.h"
#include "zsocket.h"
#include "zsockopt.h"
#include "zstr.h"
View
77 include/zskiplist.h
@@ -0,0 +1,77 @@
+/* =========================================================================
+ zsklist - a skip list
+
+ -------------------------------------------------------------------------
+ Copyright (c) 1991-2012 iMatix Corporation <www.imatix.com>
+ Copyright other contributors as noted in the AUTHORS file.
+
+ This file is part of CZMQ, the high-level C binding for 0MQ:
+ http://czmq.zeromq.org.
+
+ This is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or (at
+ your option) any later version.
+
+ This software is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+ =========================================================================
+*/
+
+
+
+
+#ifndef __ZSKIPLIST_H_INCLUDED__
+#define __ZSKIPLIST_H_INCLUDED__
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct _zsklnode_t zsklnode_t;
+
+ typedef struct _zsklist_t zsklist_t;
+
+// Create a new skip list
+ CZMQ_EXPORT zsklist_t *zsklist_new (void);
+
+// Destroy a skip list
+ CZMQ_EXPORT void zsklist_destroy (zsklist_t ** zsklist);
+
+// Add a strictly postive key to the skip list, returns 0 if already present
+ CZMQ_EXPORT int zsklist_add (zsklist_t * zsklist, uint64_t key);
+
+// Remove a key from the skip list, returns 0 if not present
+ CZMQ_EXPORT int zsklist_delete (zsklist_t * zsklist, uint64_t key);
+
+// Search a key, returns the key or zero if not present
+ CZMQ_EXPORT uint64_t zsklist_search (zsklist_t * zsklist, uint64_t key);
+
+// Search a key between 2 limits, returns the zsklist node that contains it
+ CZMQ_EXPORT zsklnode_t *zsklist_lsearch (zsklist_t * t, uint64_t key,
+ zsklnode_t * rlimit,
+ zsklnode_t * llimit);
+
+
+// Selt test of this class
+ void zsklist_test (int verbose);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+
+#endif
View
6 src/Makefile.am
@@ -18,7 +18,8 @@ include_HEADERS = \
../include/zsocket.h \
../include/zsockopt.h \
../include/zstr.h \
- ../include/zthread.h
+ ../include/zthread.h \
+ ../include/zskiplist.h
libczmq_la_SOURCES = \
zclock.c \
@@ -33,7 +34,8 @@ libczmq_la_SOURCES = \
zsocket.c \
zsockopt.c \
zstr.c \
- zthread.c
+ zthread.c \
+ zskiplist.c
INCLUDES = -I$(top_srcdir)/include
bin_PROGRAMS = czmq_selftest
View
1  src/czmq_selftest.c
@@ -51,6 +51,7 @@ int main (int argc, char *argv [])
zsockopt_test (verbose);
zstr_test (verbose);
zthread_test (verbose);
+ zsklist_test (verbose);
printf ("Tests passed OK\n");
return 0;
}
View
318 src/zskiplist.c
@@ -0,0 +1,318 @@
+/* =========================================================================
+ zsklist - a skip list
+
+ -------------------------------------------------------------------------
+ Copyright (c) 1991-2012 iMatix Corporation <www.imatix.com>
+ Copyright other contributors as noted in the AUTHORS file.
+
+ This file is part of CZMQ, the high-level C binding for 0MQ:
+ http://czmq.zeromq.org.
+
+ This is free software; you can redistribute it and/or modify it under
+ the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or (at
+ your option) any later version.
+
+ This software is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program. If not, see
+ <http://www.gnu.org/licenses/>.
+ =========================================================================
+*/
+
+
+#include "../include/czmq.h"
+
+#define MAX_NODE_HEIGHT 64
+
+//height represents the forward non null characters
+//not the actual height of the node
+//the actual height of the node can be discovered through searching
+
+struct _zsklnode_t
+{
+ int height;
+ struct _zsklnode_t **next;
+ uint64_t key;
+};
+
+
+int
+comp_node_t (zsklnode_t * first, zsklnode_t * second)
+{
+ if (first->key > second->key) {
+ return 1;
+ }
+ else {
+
+ if (first->key < second->key) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
+ }
+
+}
+
+
+zsklnode_t *
+node_new (uint64_t key)
+{
+ zsklnode_t *node = zmalloc (sizeof (zsklnode_t));
+ node->key = key;
+
+ return node;
+}
+
+void
+node_destroy (zsklnode_t ** node)
+{
+ if ((*node)->next) {
+ free ((*node)->next);
+ }
+ free (*node);
+ node = NULL;
+}
+
+
+
+
+
+struct _zsklist_t
+{
+ zsklnode_t *head;
+};
+
+
+zsklist_t *
+zsklist_new (void)
+{
+ zsklist_t *zsklist = malloc (sizeof (zsklist_t));
+ zsklist->head = node_new (0);
+ zsklist->head->height = 1;
+ zsklist->head->next = zmalloc (sizeof (zsklnode_t *));
+ return zsklist;
+}
+
+void
+zsklist_destroy (zsklist_t ** zsklist)
+{
+
+ while ((*zsklist)->head->next[0]) {
+ zsklist_delete (*zsklist, (*zsklist)->head->next[0]->key);
+ }
+ free ((*zsklist)->head->next);
+ free ((*zsklist)->head);
+ free (*zsklist);
+ zsklist = NULL;
+
+}
+
+
+int
+zsklist_add_ (zsklist_t * zsklist, int height, uint64_t key)
+{
+ assert (key > 0);
+ zsklnode_t *node = node_new (key);
+
+ zsklnode_t *prev_list[height];
+
+ int iter = height;
+ zsklnode_t *ptr = zsklist->head;
+ while (iter) {
+ if (!(ptr->next[iter - 1])) {
+ prev_list[iter] = ptr;
+ iter--;
+ }
+ else {
+ int comp = comp_node_t (node, ptr->next[iter - 1]);
+ if (comp == 1) {
+ ptr = ptr->next[iter - 1];
+ }
+ else {
+ if (comp == -1) {
+ prev_list[iter] = ptr;
+ iter--;
+ }
+ else {
+ node_destroy (&node);
+ return 0;
+ }
+ }
+ }
+ }
+
+ node->height = 1;
+ if ((node->height < MAX_NODE_HEIGHT) && ((rand () % 4) == 0)) {
+ node->height++;
+ }
+
+ node->next = zmalloc (node->height * sizeof (zsklnode_t *));
+
+ for (iter = 1; iter <= height; iter++) {
+ node->next[iter - 1] = prev_list[iter]->next[iter - 1];
+ prev_list[iter]->next[iter - 1] = node;
+ }
+
+ return 1;
+
+}
+
+//returns 0 if the key already exists
+int
+zsklist_add (zsklist_t * zsklist, uint64_t key)
+{
+ return zsklist_add_ (zsklist, zsklist->head->height, key);
+}
+
+int
+zsklist_delete_ (zsklist_t * zsklist, int height, uint64_t key)
+{
+
+ assert (key > 0);
+ zsklnode_t node;
+ node.key = key;
+
+ zsklnode_t *prev_list[height];
+
+ int iter = height;
+ zsklnode_t *ptr = zsklist->head;
+ int comp = 1;
+ while (iter) {
+ if (!(ptr->next[iter - 1])) {
+ prev_list[iter] = ptr;
+ iter--;
+ }
+ else {
+ comp = comp_node_t (&node, ptr->next[iter - 1]);
+ if (comp == 1) {
+ ptr = ptr->next[iter - 1];
+ }
+ else {
+ prev_list[iter] = ptr;
+ iter--;
+
+ }
+ }
+ }
+
+ if (!comp) {
+ ptr = ptr->next[0];
+
+ for (iter = 1; iter <= height; iter++) {
+ prev_list[iter]->next[iter - 1] = ptr->next[iter - 1];
+ }
+ node_destroy (&ptr);
+
+
+ return 1;
+
+ }
+ else {
+ return 0;
+
+ }
+}
+
+
+int
+zsklist_delete (zsklist_t * zsklist, uint64_t key)
+{
+ return zsklist_delete_ (zsklist, zsklist->head->height, key);
+}
+
+
+
+
+uint64_t
+zsklist_search (zsklist_t * zsklist, uint64_t key)
+{
+ if (zsklist_lsearch (zsklist, key, zsklist->head, NULL)) {
+ return key;
+ }
+ else {
+ return 0;
+ }
+
+}
+
+zsklnode_t *
+zsklist_lsearch (zsklist_t * t, uint64_t key,
+ zsklnode_t * rlimit, zsklnode_t * llimit)
+{
+ zsklnode_t node;
+ node.key = key;
+
+ int iter = rlimit->height;
+ if (llimit) {
+ if (llimit->height < iter) {
+ iter = llimit->height;
+ }
+ }
+ zsklnode_t *ptr = rlimit;
+ while (iter) {
+ if (!(ptr->next[iter - 1])) {
+ iter--;
+ }
+ else {
+ int comp = comp_node_t (&node, ptr->next[iter - 1]);
+ if (comp == 1) {
+ ptr = ptr->next[iter - 1];
+ }
+ else {
+ if (comp == -1) {
+ iter--;
+ }
+ else {
+ return ptr;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+void
+zsklist_test (int verbose)
+{
+ printf (" * zsklist: ");
+ zsklist_t *list = zsklist_new ();
+
+ uint64_t key[100];
+ int iter;
+ for (iter = 0; iter < 100; iter++) {
+ key[iter] = rand () % 10000 + 1;
+ zsklist_add (list, key[iter]);
+ }
+ if (verbose) {
+ printf ("\nkey:%lu , search result:%lu", key[77],
+ zsklist_search (list, key[77]));
+ printf ("\nkey:%lu , search result:%lu", key[33],
+ zsklist_search (list, key[33]));
+ printf ("\nkey:%lu , search result:%lu", key[66],
+ zsklist_search (list, key[66]));
+ printf ("\nkey:%lu , search result:%lu", key[22],
+ zsklist_search (list, key[22]));
+ }
+ assert (key[77] == zsklist_search (list, key[77]));
+ assert (key[33] == zsklist_search (list, key[33]));
+ assert (key[66] == zsklist_search (list, key[66]));
+ assert (key[22] == zsklist_search (list, key[22]));
+
+ assert (zsklist_delete (list, key[77]));
+ assert (0 == zsklist_search (list, key[77]));
+
+ assert (zsklist_delete (list, key[33]));
+ assert (0 == zsklist_search (list, key[33]));
+
+ zsklist_destroy (&list);
+
+ printf ("OK\n");
+}
Something went wrong with that request. Please try again.