Skip List implementation terminated without initialization

103 Views Asked by At

I am trying to implement skip list with insertion and search operation. I am unable to spot a mistake why the program is not working properly even after using -Wall -Wextra options and eliminating all the warnings and errors.

The program is not even able to initialize the skip list. I have tried hours. Please help me. My implementation is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <limits.h>

#define Malloc(n, type) (type *)malloc((unsigned)((n) * sizeof(type)))
#define Realloc(ptr, n, type) (type *)realloc(ptr, (n) * sizeof(type))

typedef struct Node
{
    int key;
    struct Node *next;
    struct Node *down;
} Node;

typedef struct
{
    int level;
    struct Node *header;
} skiplist;

static int coin_flip()
{
    /*
    This function simulates a coin flip.

    arg: void
    return: a number from the set {0,1}
    */
    srand(time(NULL));
    return (rand() % 2);
}

static int level()
{
    /*
    This function takes the coin flip and decides the level of the node with each
    level having a probability of 0.25.

    arg: void
    return: a number from the set {1,2,3, 4}
    */
    int level = 1;
    for (int i = 0; i < 3; i++)
    {
        if (coin_flip())
        {
            level++;
        }
        else
            break;
    }
    return level;
}

void skip_list_init(skiplist *);

Node *Traverse_Express(Node *, int);

Node *skip_list_search(skiplist *, int);

void insert_level(Node *, int, int, int);

void skip_list_insert(skiplist *, int);

void skip_print(skiplist *);

int main()
{
    srand(time(NULL));
    int arr[10000];
    for (int i = 0; i < 10000; i++)
    {
        arr[i] = (int)rand();
    }
    printf("The array is initialised\n");
    skiplist *list = NULL;
    skip_list_init(list);
    printf("The Skip list is initialised\n");
    for (int i = 0; i < 10; i++)
    {
        skip_list_insert(list, arr[i]);
        printf("The %d element is initialised with key: %d\n", i, arr[i]);
    }
    printf("The skip list is:\n");
    skip_print(list);
    return 0;
}

void skip_print(skiplist *list)
{
    /*
    The function prints the skip list level-wise.

    arg: list
    return: none
    */
    Node *temp = list->header;
    int count = 0;
    for (int i = list->level; i > 0; i--)
    {
        printf("The Keys at level %d:\n", i);
        while (NULL != temp->next)
        {
            printf("%d ->", temp->key);
            temp = temp->next;
        }
        printf("%d\n", temp->key);
        int dummy = count;
        temp = list->header;
        while (dummy)
        {
            temp = temp->down;
        }
        count++;
    }
}

void skip_list_init(skiplist *list)
{
    /*
    This function creates the first node in the skip list with key value
    to be negative infinity and level of the list =1.

    arg: It takes a list by reference
    return: None
    */
    Node *head = Malloc(1, Node);
    list->level = 1;
    list->header = head;
    head->key = INT_MIN;
    head->next = NULL;
    head->down = NULL;
}

Node *skip_list_search(skiplist *list, int key)
{
    /*
    1. The function returns the previous pointer to the required node.
    2. next_is_req is returned because only one more step is required in case of
       sucessful or unsucessful search.
    3. In case of deletion, the previous node is required for linkage.

    arg: A skip list of type skiplist, and a key of type int.
    return: A previous node (next_is_req) to the required node with or
            without key.
    */

    int level = list->level; // Number of levels already present in the list
    Node *next_is_req = NULL, *curr = list->header;
    for (; level > 0; level--)
    {
        if ((curr->key == key) && (INT_MIN != curr->key || INT_MAX != curr->key))
        {
            return next_is_req;
        }
        while ((key > curr->key) && (NULL != curr->next))
        {
            if (key < curr->next->key)
            {
                next_is_req = curr;
                curr = curr->next;
            }
            else
            {
                break;
            }
        }
        if (NULL != curr->down)
        {
            next_is_req = curr;
            curr = curr->down;
        }
    }
    return next_is_req;
}

Node *Traverse_Express(Node *temp, int key)
{
    while (key > temp->key && NULL != temp->next)
    {
        temp = temp->next;
    }
    return temp;
}

void insert_level(Node *nod, int key, int lev, int list_lev)
{
    /*
    Inserting the key till the required level

    arg:
        nod: a pointer to the exsiting skip list
        key: key to be inserted
        lev: the level of the key
        list_lev: the number of levels in the given skiplist

    return: None
    */
    Node *temp1 = nod, *temp3 = NULL;
    // Procedure to cut-off the extra levels in the list if any
    if (lev < list_lev)
    {
        for (int i = list_lev - lev; i > 0; i--)
        {
            temp1 = Traverse_Express(temp1, key);
            temp1 = temp1->down;
        }
    }
    // Procedure to insert from the required level till level 1
    for (int i = 0; i < lev; i++)
    {
        Node *temp2 = Malloc(1, Node);
        temp2->key = key;
        temp2->next = NULL;
        temp2->down = NULL;
        temp1 = Traverse_Express(temp1, key);
        if (NULL == temp1->next)
        {
            temp1->next = temp2;
        }
        else
        {
            temp2->next = temp1->next;
            temp1->next = temp2;
        }
        if (i > 0)
        {
            temp3->down = temp2;
        }
        temp1 = temp1->down;
        temp3 = temp2;
    }
}

void skip_list_insert(skiplist *list, int key)
{
    /*
    This function finds the key value and if already present, then returns back
    else it inserts the key at its right place.



    arg: a skilplist by reference and a key
    return: None
    */
    Node *next_req = skip_list_search(list, key);
    if (key == next_req->next->key)
    {
        printf("Key %d is already present in skip list", key);
        return;
    }
    Node *temp1 = list->header;
    int list_lev = list->level;
    int lev = level();
    Node *temp2 = NULL;
    // creating a skip list if level returned is greater than existing one.
    if (lev > list->level)
    {
        for (int i = lev - list_lev; i > 0; i--)
        {
            skip_list_init(list);
            Node *inser = Malloc(1, Node);
            inser->key = key;
            list->header->next = inser;
            Node *temp3 = list->header;
            while (temp2)
            {
                temp3->down = temp2;
                temp3 = temp3->next;
                temp2 = temp2->next;
            }
            temp2 = list->header;
            list = NULL;
        }
        list->header = temp2;
        while (NULL != temp2->down)
        {
            temp2 = temp2->down;
        }
    }
    // Inserting the node till the min(list_lev, level())
    if (list_lev > lev)
    {
        insert_level(temp1, key, lev, list_lev);
    }
    else
    {
        insert_level(temp1, key, list_lev, list_lev);
    }
    // Zipping Procedure only if level()>list_lev
    if (lev > list_lev)
    {
        temp2 = list->header;
        while (NULL != temp2->down)
        {
            temp2 = temp2->down;
        }
        temp2->down = temp1;
        temp2 = temp2->next;
        while (temp1->key != key)
        {
            temp1 = temp1->next;
        }
        temp2->down = temp1;
        list->level = lev;
    }
}

Thanks in advance.

0

There are 0 best solutions below