Monday, March 9, 2015

Swap Kth node from beginning with Kth node from end in a Linked List

Given a singly linked list, swap kth node from beginning with kth node from end. Swapping of data is not allowed, only pointers should be changed. This requirement may be logical in many situations where the linked list data part is huge (For example student details line Name, RollNo, Address, ..etc). The pointers are always fixed (4 bytes for most of the compilers).
Linked List

code : 


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



struct node 
{
int data;
  struct node * link;
};


struct node *createNode(int data)
{
struct node *p=NULL;
p=(struct node *)malloc(sizeof(struct node));
p->data=data;
p->link=NULL;

return p;

}



struct node *traverseTillEnd(struct node *head) //will return the pointer to the last node.
{
struct node *p=head;

if(head==NULL)
{
return NULL;
}
else
{
while((p->link)!=NULL)
{
p=p->link;
}

return p;
}


}





struct node *insert(struct node * head,int data)
{
struct node *p=NULL;

if(head==NULL)
{
head=createNode(data);
return head;
}
else
{
// traverse the node till end.
p=traverseTillEnd(head);
p->link=createNode(data);
return head;
}


}



int count(struct node *head) // return the number of nodes the list have.
{
int i=0;
if(head==NULL)
{
return 0;
}
else
{
while(head!=NULL)
{
i++;
head=head->link;
}
return i;
}

}

void printList(struct node *head)
{
while(head!=NULL)
{
printf("-%d-",(head->data));
head=head->link;
}

printf("\n");

}

struct node * swap(struct node *head,int k) // takes head of the linked list and k value as argument.
{
struct node *temp1=NULL,*temp2=NULL,*tempp1=NULL,*tempp2=NULL;
struct node *x=NULL,*y=NULL;
struct node * temp=NULL;
int total=count(head);

// find the kth node from starting.
if(k>total)
{
return head;    // I can not return NULL because , it will affect my original linked list , as I am storing return value of this function to the head of the list.
}

if(k==0)
{
return head;  // no change...
}

x=head;

while(k!=1)
{
temp1=x;
x=x->link;
k--;
}

tempp1=x->link;

// at this point x is pointing to the kth location form starting node of the list.

// now I have to find the kth node form last.

y=head;
temp=x;

while((temp->link)!=NULL)
{
temp2=y;
y=y->link;
temp=temp->link;
}
tempp2=y->link;

// at this point y is pointing to the kth location form last node of the list.
// test all the variables..

/*
printf("\n%d\n",temp1->data);
printf("\n%d\n",x->data);
printf("\n%d\n",tempp1->data);
printf("\n%d\n",temp2->data);
printf("\n%d\n",y->data);
printf("\n%d\n",tempp2->data);
*/

// let swapping process starts

if((x->link)==y) // y is next to x
{
temp1->link=y;
x->link=tempp2;
y->link=x;

}
else if((y->link)==x) // x is next to y
{
temp2->link=x;
x->link=y;
y->link=temp1;
}
else if(x==y)
{
// then why to swap ?
}
else if(x==head) // it is possible that x is pointing to head node , then its time to change my head node.
{

temp2->link=x;
x->link=NULL;
y->link=tempp1;
head=y;

}
else if(y==head) // it is possible that y is pointing to head node , then its time to change my head node.
{

temp1->link=y;
y->link=NULL;
x->link=tempp2;
head=x;
}
else // normal cases.
{
y->link=x->link;
temp1->link=y;
x->link=tempp2;
temp2->link=x;

}

return head;

}


int main(int argc,char *argv[])
{
int i=0;
int val[argc];
struct node *head=NULL;
printf("%d number of argument provided.\n",(argc-1));

for(i=1;i<argc;i++)
{
val[i]=atoi(argv[i]); // convert Ascci to Int
head=insert(head,val[i]);
}

printList(head);
head=swap(head,1);

printList(head);
return 0;


}


// compile : gcc -c swap.c
// link : gcc -o swap swap.o
// execute : ./swap 10 15 20 25 26 28 29 35 40 42 44 45 48

// all comments are invited , please let me know if code fails for particular case.

Skip List | Set 1 (Introduction)

Can we search in a sorted linked list in better than O(n) time?
The worst case search time for a sorted linked list is O(n) as we can only linearly traverse the list and cannot skip nodes while searching. For a Balanced Binary Search Tree, we skip almost half of the nodes after one comparison with root. For a sorted array, we have random access and we can apply Binary Search on arrays.
Can we augment sorted linked lists to make the search faster? The answer is Skip List. The idea is simple, we create multiple layers so that we can skip some nodes. See the following example list with 16 nodes and two layers. The upper layer works as an “express lane” which connects only main outer stations, and the lower layer works as a “normal lane” which connects every station. Suppose we want to search for 50, we start from first node of “express lane” and keep moving on “express lane” till we find a node whose next is greater than 50. Once we find such a node (30 is the node in following example) on “express lane”, we move to “normal lane” using pointer from this node, and linearly search for 50 on “normal lane”. In following example, we start from 30 on “normal lane” and with linear search, we find 50.
What is the time complexity with two layers? The worst case time complexity is number of nodes on “express lane” plus number of nodes in a segment (A segment is number of “normal lane” nodes between two “express lane” nodes) of “normal lane”. So if we have n nodes on “normal lane”, \sqrt{n} nodes on “express lane” and we equally divide the “normal lane”, then there will be \sqrt{n} nodes in every segment of “normal lane” . \sqrt{n} is actually optimal division with two layers. With this arrangement, the number of nodes traversed for a search will be O(\sqrt{n}). Therefore, with O(\sqrt{n}) extra space, we are able to reduce the time complexity to O(\sqrt{n}).




problem defination is available at : skip-list

code :


#include<stdio.h>
#include<stdlib.h>
#include<math.h>


struct node
{
int data;
  struct node * link;
};

struct skipNode
{
int data;
struct node *ll;
struct skipNode *link;

};

struct node *createNode(int data)
{
struct node *p=NULL;
p=(struct node *)malloc(sizeof(struct node));
p->data=data;
p->link=NULL;

return p;

}


struct skipNode *createSkipNode(struct node *ll)
{
struct skipNode *p=NULL;
p=(struct skipNode *)malloc(sizeof(struct skipNode));
p->data=ll->data;
p->ll=ll;
p->link=NULL;

return p;

}


struct node *traverseTillEnd(struct node *head) //will return the pointer to the last node.
{
struct node *p=head;

if(head==NULL)
{
return NULL;
}
else
{
while((p->link)!=NULL)
{
p=p->link;
}

return p;
}


}

struct skipNode *traverseSkipTillEnd(struct skipNode *head)
{
struct skipNode *p=NULL;
p=head;

if(head==NULL)
{
return NULL;
}
else
{
while((p->link)!=NULL)
{
p=p->link;
}

return p;


}


}



struct node *insert(struct node * head,int data)
{
struct node *p=NULL;

if(head==NULL)
{
head=createNode(data);
return head;
}
else
{
// traverse the node till end.
p=traverseTillEnd(head);
p->link=createNode(data);

return head;
}


}


struct skipNode *skipInsert(struct skipNode *head,struct node *ll) // pass the head of skip node , link to the linked list node.
{
struct skipNode *p=NULL;

printf("insid insert...\n");

if(head==NULL)
{
head=createSkipNode(ll);
printf("\n data is %d",head->data);
return head;
}
else
{
printf("insid else...\n");
// traverse the skipList to the end...
p=traverseSkipTillEnd(head);
printf("\n data is %d\n",p->data);
p->link=createSkipNode(ll);

return head;
}

}

int count(struct node *head) // return the number of nodes the list have.
{
int i=0;
if(head==NULL)
{
return 0;
}
else
{
while(head!=NULL)
{
i++;
head=head->link;
}

return i;
}

}

void printList(struct node *head)
{
while(head!=NULL)
{
printf("-%d-",(head->data));
head=head->link;
}

printf("\n");

}


void printSkipList(struct skipNode *head)
{
while(head!=NULL)
{
printf("-%d-",(head->data));
head=head->link;
}

printf("\n");

}



struct skipNode *createSkipList(struct node *head) // create new linked list , called skip list and return the pointer to the head node of the skip list.
{
int skipNodeCount;
int nodeCount=count(head);
int segmentCount=0;
int temp;
struct skipNode *skipHead=NULL;
struct node *ptrToLL=NULL;


if(head==NULL)
{
return NULL;
}
else
{

skipNodeCount=(int)sqrt((double)count(head));

printf("\n\n %d\n",skipNodeCount);

// decide how many number of nodes shoud be between two skip list nodes , lets call it Segment.

segmentCount=nodeCount/skipNodeCount;

printf("\n\n %d\n",segmentCount);

// create the skip list.

ptrToLL=head;





while(skipNodeCount!=0)
{

skipHead=skipInsert(skipHead,ptrToLL);

if(skipNodeCount==1)
{
break;
}

ptrToLL=ptrToLL->link;
temp=segmentCount;

while(temp!=0)
{

ptrToLL=ptrToLL->link;
temp--;

}


skipNodeCount--;

}


}


return skipHead;


}


int main(int argc,char *argv[])
{
int i=0;
int val[argc];
struct node *head=NULL;
struct skipNode *skipHead=NULL;

printf("%d number of argument provided.\n",(argc-1));

for(i=1;i<argc;i++)
{
val[i]=atoi(argv[i]); // convert Ascci to Int

head=insert(head,val[i]);

}

printList(head);

skipHead=createSkipList(head);

printf("\n\n");

printSkipList(skipHead);

return 0;


}


// now  create the function to find the element in the linked list from the searching in the skip list by your own,

// compile :  gcc -c skipList.c
// link :  gcc -o skipList skipList.o -lm
// execute :  ./skipList 10 15 20 25 26 28 29 25 40 45