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.