"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > skiplist implementation

skiplist implementation

Published on 2024-11-25
Browse:510

skiplist implementation

I share here my skiplist implementation. It is a good idea to keep in trained on C language.

#include 
#include 
#include 

#define LOGLEVEL 3

// a skip list is made of a single linked where each element has an
// array of pointers to the next element of the same level.
// I will name `level_pointer` the array of pointers,
// for each element "e" in the list e.level_pointer[n] points to
// the next element "e1" at the same level.
// Every pointer with m smaller than n, the e.level_pointer[m] points
// to an element "e2" such that e =m such that
// e level_pointer = (struct skiplist**) calloc(1, sizeof(struct skiplist*));
    slc->maxlevel = 1;
    slc->level_pointer[0] = NULL;
    slc->cmp = cmp;
    return slc;
}

void logit(const char *restrict format, ...) {
    va_list ap;
    va_start( ap, format );
    vprintf(format, ap);
}

void sklist_insert(struct sklist* slc, void *element) {
    // create the new node
    struct skiplist * sknode = (struct skiplist*) malloc(sizeof(struct skiplist*));
    sknode->element = element;
    sknode->maxlevel = 1;
    // toss a coin to determine the element maxlevel
    while ((rand() % 2) == 1)  {
        sknode->maxlevel  ;
    }
    #if LOGLEVEL == 3
    logit("INSERTING %d at LEVE %d\n",*(int*)element, sknode->maxlevel);
    #endif
    sknode->level_pointer = (struct skiplist**) calloc(sknode->maxlevel, sizeof(struct skiplist*));
    int from_level = sknode->maxlevel-1;
    if (sknode->maxlevel > slc->maxlevel ) {
        // if the new element has the tallest level_pointer
        // it means all the pointers with higher level points to the new element
        slc->level_pointer = (struct skiplist**) realloc(slc->level_pointer, sknode->maxlevel * sizeof(struct skiplist*));
        int i;
        for (i = slc->maxlevel; imaxlevel; i  ) {
            slc->level_pointer[i] = sknode;
            sknode->level_pointer[i] = NULL;
        }
        from_level = slc->maxlevel - 1;
        slc->maxlevel = sknode->maxlevel;
    }
    // starting from_level the insertion must be checked
    struct skiplist ** left_p = slc->level_pointer;
    for(;from_level>=0;from_level--) {
        // peak the next element pointed, still staying a position before
        // keeping in mind that head is smaller than anything,
        // then left_p belong to something smaller than sknode
        while( (left_p[from_level] != NULL) && slc->cmp(left_p[from_level]->element, sknode->element)level_pointer;
        }
        sknode->level_pointer[from_level] = left_p[from_level];
        left_p[from_level] = sknode;
    #if LOGLEVEL == 3
        logit("Inserted %d\n", *(int*) sknode->element);
    #endif
        //printf("left %d\n", *(int*) left_p[from_level]->level_pointer[from_level]->element);
    }
}

struct skiplist * sklist_exists(struct sklist* slc, void *element) {
    // search for element and return it if it exists, return NULL otherwise
    int maxlevel = slc->maxlevel-1;
    struct skiplist ** lpoint = slc->level_pointer;
    for (;maxlevel>=0; maxlevel--) {
        struct skiplist ** prev;
        while (lpoint[maxlevel]!=NULL && slc->cmp(lpoint[maxlevel]->element, element) element, maxlevel);
            prev = lpoint;
            lpoint = lpoint[maxlevel]->level_pointer;
        }
        if (lpoint[maxlevel]!=NULL && slc->cmp(lpoint[maxlevel]->element, element) == 0) {
            return lpoint[maxlevel];
        } else {
            lpoint = prev;
        }
    }
    return NULL;
}

struct skiplist * sklist_extract(struct sklist* slc, void *element) {
    // search for element and return it if it exists, return NULL otherwise
    int maxlevel = slc->maxlevel-1;
    struct skiplist ** lpoint = slc->level_pointer;
    struct skiplist * el_pile = NULL;
    while (maxlevel>=0) {
        struct skiplist ** prev = NULL;
        while (lpoint[maxlevel]!=NULL && slc->cmp(lpoint[maxlevel]->element, element) element, maxlevel);
            #endif
            prev = lpoint;
            lpoint = lpoint[maxlevel]->level_pointer;
        }
        if (lpoint[maxlevel]!=NULL && slc->cmp(lpoint[maxlevel]->element, element) == 0) {
            #if LOGLEVEL == 3
            logit("FOUND HHHHH l:%d\n",lpoint[maxlevel]->maxlevel);
            #endif
            // remove everything from this level here to below:
            if (el_pile == NULL && lpoint[maxlevel]->maxlevel == slc->maxlevel)  {
                el_pile = lpoint[maxlevel];
                // it must resize the maxlevel of the main structure
                // for this just inspect the main level_pointer and this element level_pointer
                // until the second one is NULL and the first one is exactly this element
                // reduce the maxlevel of the mail structure
                int i = el_pile->maxlevel-1;
                while(i>0 && (slc->level_pointer[i] == el_pile && el_pile->level_pointer[i] == NULL)) i--;
                slc->maxlevel = i 1; // the level is the size
                maxlevel = slc->maxlevel;
                #if LOGLEVEL == 3
                logit("shrink level %d\n", maxlevel);
                #endif
            }
            // eat one pos
            lpoint[maxlevel] = lpoint[maxlevel]->level_pointer[maxlevel];
        } else {
            lpoint = prev;
        }
        maxlevel--;
    }
    return el_pile;
    //return NULL;
}

int compare_ints(void *X, void *Y) {
    int *x = (int*) X;
    int *y = (int*) Y;
    if(*xmaxlevel);
    int l = slc->maxlevel;
    for(int i=0;ilevel_pointer[i];
        printf("\nLEVEL: %d\n",i);
        while (head != NULL) {
            printf("%d\t-\t", *(int*) (head->element));
            head = head->level_pointer[i];
        }
    }
    printf("\n");
}

void pile_print_it(struct sklist* slc) {
    printf("PILE staff: maxlevel: %d\n", slc->maxlevel);
    int l = slc->maxlevel;
    for(int i=0;ilevel_pointer[i];
        struct skiplist * head0 = slc->level_pointer[0];
        while (head != NULL) {
            while (head0!= head) {
                printf("--\t-\t");
                head0 = head0->level_pointer[0];
            }
            printf("%d\t-\t", *(int*) (head->element));
            head = head->level_pointer[i];
            head0 = head0->level_pointer[0];
        }
    }
    printf("\n");
}

int main() {
    int *i;
    *i = 190;
    int j = 12;
    printf("COMPARE %d vs %d : %d\n", j, *i, compare_ints((void*) &j, (void *) i));
    // *j = 12;
    struct sklist *skipl = create_skip(compare_ints);
    print_it(skipl);
    sklist_insert(skipl, (void*)i);
    print_it(skipl);
    sklist_insert(skipl, (void*)&j);
    print_it(skipl);
    int k = 23;
    sklist_insert(skipl, (void*)&k);
    print_it(skipl);
    int kk = 123;
    sklist_insert(skipl, (void*)&kk);
    pile_print_it(skipl);
    int kk2 = 23;
    struct skiplist *el = sklist_exists(skipl, (void*) &kk2);
    if(el!=NULL) {
        printf("FOUND!!!!!\n");
    } else {
        printf("NOOOOT FOUND!!\n");
    }
    for(;;) {
        printf("command (I_nsert/L_ookup): \n");
        char command = (char) getchar();
        //if (command == '\n') command = (char) getchar();
        switch (command) {
            case 'i':
            case 'I':
            {
                printf("insert a num: ");
                int *xx = malloc(sizeof(int));
                scanf("%d", xx);
                sklist_insert(skipl, (void*)xx);
                pile_print_it(skipl);
            }
            break;
            case 'l':
            case 'L':
            {
                printf("lookup a num: ");
                int *xx = malloc(sizeof(int));
                scanf("%d", xx);
                struct skiplist *el = sklist_exists(skipl, (void*) xx);
                if(el!=NULL) {
                    printf("%d FOUND!!!!!\n", *xx);
                } else {
                    printf("%d NOOOOT FOUND!!\n", *xx);
                }
            }
            break;
            case 'e':
            case 'E':
            {
                printf("extract a num: ");
                int *xx = malloc(sizeof(int));
                scanf("%d", xx);
                struct skiplist *el = sklist_extract(skipl, (void*) xx);
                if(el!=NULL) {
                    printf("%d FOUND!!!!!\n", *xx);
                } else {
                    printf("%d NOOOOT FOUND!!\n", *xx);
                }
                //free(el);
            }
            case 'p':
            case 'P':
                pile_print_it(skipl);
                break;
            case 'x':
                return 0;
        }
    }
}

there is some bugs in there, to be fixed

Release Statement This article is reproduced at: https://dev.to/danielecr/skiplist-implementation-3h2j If there is any infringement, please contact [email protected] to delete it
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3