I am currently solving sum problems of list and function and i came across this question i.e rotate a linked list by k anti clockwise.
Here is the code for same
void rotate_k(struct list *node,int k)
{
int count=0;
struct list *knode,*ptr=node;
while(ptr!=NULL && count < k)
{
ptr=ptr->next;
count++;
}
knode=ptr;
while(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next =node;
node=knode->next;
knode->next=NULL;
}
Lets say if input is 1->2->3->4->5->6 and k=4.
The output should be 5->6->1->2->3->4 but the code gives the output 1->2->3->4->5 .
Help needed :)
You are not modifying the original list (node parameter)
struct list *rotate_k(struct list *node,int k)
{
int count=0;
struct list *knode,*ptr=node;
while(ptr!=NULL && count < k)
{
ptr=ptr->next;
count++;
}
knode=ptr;
while(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next =node;
node=knode->next;
knode->next=NULL;
return knode; //<-- THIS IS THE NEW LIST
}
Also, knode->next=NULL is strange; you should do at the node that is (was) previous to knode (this is what is deleting the 6 from your results).
SJuan's method is correct but if you want to do it your way without using a return value, then you need to use a double pointer for node. Remember, C makes copies of variables you pass into a function. If the original root node was a pointer (which I'm assuming it was) than you need to make a pointer to a pointer otherwise you are just making changes to a copy of the root node pointer, not the actual root node pointer.
void rotate_k(struct list **node, int k)
{
int count = 0;
struct list *knode, *ptr = *node;
while(ptr != NULL && count < k)
{
ptr = ptr->next;
count++;
}
knode = ptr;
while(ptr->next != NULL)
{
ptr = ptr->next;
}
ptr->next = *node;
*node = knode->next;
knode->next = NULL;
}
void rotate_list_right(listnode** head, int k)
{
if( !head || !*head )
{
printf( "\nrotate_list_right: empty list = so return \n" );
return;
}
if( k < 1 )
{
printf( "\nrotate_list_right:invalid input: k must be >= 1 \n" );
return;
}
listnode* post = *head;
listnode* curr = *head;
/* move post by k nodes */
while(k--)
{
post = post->next;
if( !post ) /* k is bigger than length of the list */
{
printf( "\nrotate_list_right:invalid input: k must be smaller than list size \n" );
return;
}
}
/* move curr to kth-last node */
while(post->next)
{
curr = curr->next;
post = post->next;
}
/* currs' next is new header */
listnode* tmp = *head;
*head = curr->next;
curr->next = 0;
//join post
post->next = tmp;
}
Related
I have this piece of code, it deletes the last element from a linked list. What changes do I have to make so it will delete the last TWO elements of the linked list?
void deletesEnd() {
struct node *temp, *last;
temp = head;
last = temp;
while (temp != NULL && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == temp) {
free(temp);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
}
The simplest solution to remove the last 2 elements of the list is to call deletesEnd() twice. Note that deletesEnd() should take head as an argument and return the new value. You would delete the last 2 by issuing a nested call:
struct node *deletesEnd(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
free(head);
head = NULL;
} else {
free(last->next);
last->next = NULL;
}
return head;
}
Delete the last element: head = deletesEnd(head);
Delete the last 2 elements: head = deletesEnd(deletesEnd(head));
The simplicity of the design more than compensates for the overhead of enumerating the list twice.
If you absolutely want a specific function, you can extend your approach this way:
struct node *deleteLast2Nodes(struct node *head) {
struct node *temp, *last;
last = temp = head;
while (temp && temp->next != NULL && temp->next->next != NULL) {
last = temp;
temp = temp->next;
}
if (last == head) {
if (head) {
free(head->next);
}
free(head);
head = NULL;
} else {
free(last->next->next);
free(last->next);
last->next = NULL;
}
return head;
}
Here is a demonstrative program that shows how two last nodes can be deleted simultaneously. In fact the function is similar to your function except it checks not only the next node but also the next->next node.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int value;
struct node *next;
} *head;
void push( int value )
{
struct node *tmp = malloc( sizeof( struct node ) );
tmp->value = value;
tmp->next = head;
head = tmp;
}
void display()
{
for ( struct node *current = head; current; current = current->next )
{
printf( "%d ", current->value );
}
}
void deleteLastTwo()
{
struct node *current = head;
struct node *prev = head;
if ( current && current->next )
{
while ( current->next->next )
{
prev = current;
current = current->next;
}
}
if ( current )
{
if ( current->next )
{
free( current->next );
}
if ( prev == current )
{
head = NULL;
}
else
{
prev->next = NULL;
}
free( current );
}
}
int main(void)
{
const int N = 11;
for ( int i = N; i != 0; i-- ) push( i - 1 );
display();
printf( "\n" );
while ( head )
{
deleteLastTwo();
display();
printf( "\n" );
}
return 0;
}
The program output is
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8
0 1 2 3 4 5 6
0 1 2 3 4
0 1 2
0
Take into account that it is not a good idea when the head node is declared like a global variable. It is better when it can be declared like a local variable. In this case you will need to rewrite the methods of the list because in most cases the current methods will not work correctly.
This logic will delete your last 2 node in singly linked list.
void deletesEnd()
{
struct node *temp, *last;
temp = head;
last = temp;
while (temp->next->next != NULL)
{
last = temp->next;
if(last->next->next!=NULL)
temp = temp->next;
else
break;
}
struct node *ptr=last->next;
last->next=ptr->next;
free(ptr);
temp->next=last->next;
free(last);
}
For fun & education: simple recursive version.
The function return := the number of nodes below us
After the recursion returns, we can decide if we are too close to the tail.
and remove ourselves
because we pass a pointer to pointer, this should also work for lists of size=2 and smaller
unsigned del_tail_n(struct llist **pp, unsigned nn)
{
unsigned pos;
if (!*pp) return 0;
// this recursive call returns 0 iff (*pp)->next is NULL
pos = del_tail_n( &(*pp)->next, nn);
if (pos < nn) {
// free (*pp);
*pp = NULL;
}
return 1+pos;
}
For those who don't like recursion, here is a non-recursive version.
[do note that both versions work for empty lists (*pp == NULL) , or for lists smaller than nn ]
void del_tail_n2(struct llist **pp, unsigned nn)
{
struct llist *p;
/* Advance p pointer n positions down, starting from *pp. */
for (p= *pp; p; p=p->next) {
if (nn-- < 1) break;
}
/* Do a synchronous walk down for both p and *pp, until p is NULL. */
for ( ; p; p=p->next) {
pp = &(*pp)->next;
}
/* Now, *pp is the first node to delete
** Delete it and everything below it.
*/
for ( ;(p = *pp); ){
*pp = p->next;
// free (p);
}
return;
}
struct node
{
int info;
struct node *next;
};
typedef struct node node;
void *printRev(node *head){
int count=0;
int i;
node *beforeFin;
node *tempHead;
tempHead = head;
while(tempHead->next != NULL){
count++;
tempHead->next = tempHead->next->next; //LAST ITERATION SHOULD BE AT THE END OF LIST
}
printf("COUNT IS: %d\n", count);
for(i = 0; i <= count; i++){
beforeFin = Prev(head, tempHead->next);
printf("%d", beforeFin->info);
}
printf("\n");
}
As of now this prints out:
COUNT IS: 3
Segmentation fault (core dumped)
Prev returns a pointer to the node before the given pointer (tempHead->next) my intention was for this to print out the singly linked list in reverse order using the for loop above. So the ->info of the given node should return 5 in the example below (after the first iteration).
Before the printf that prints the count, tempHead->next should point to the final node.
Right now I am passing in 2 3 5 4 and this is giving me the count before the 4. Id like for this to print out 4 5 3 2
I would appreciate any help given, I am a beginner as you might be able to tell. Thank you all in advance!
I could do this using recursion but I'd like to learn figure out this method.
To print a single linked list in reverse order you can use a recursive function. You have to step into the recursion to the end and print the elements of the list right before you leave the recursion function:
void printReverse(node *act)
{
if ( act == NULL ) // terminate if end of list is reached
return;
printRev( act->next ); // print next node
printf( "%d ", act->info ); // print this node
}
If you do not want to use recursion, you can of course reverse the list, then print the list and finally reverse it again.
Reversing a list is not difficult. Traverse through the list, take each element and reorder it in front of the head of the list.
node * reverse(node *head)
{
node *act, *prev;
if ( head == NULL )
return;
prev = head;
act = head->next;
while ( act != NULL )
{
prev->next = act->next;
act->next = head;
head = act;
act = prev->next;
}
return head;
}
void printReverse(node *head)
{
node *act;
act = reverse(head);
while ( act != NULL )
{
printf( "%d ", act->info ); // print this node
act = act->next;
}
reverse(head);
}
As you want to avoid recursion, you need to reverse the list first. I see some attempt in the original code but it doesn't look correct. Try the following:
node *current = head;
if (current != NULL) {
node *prev = NULL;
for (node *next = current->next; ; next = (current = next)->next) {
current->next = prev;
prev = current;
if (next == NULL)
break;
}
}
Then current will point to the head of the list and you can traverse using the next link over the list. Note that it will modify your original list but this is expected as I understood the original requirement.
The issue with the recursive algorithm is that, if you're a bit paranoid like me, the list could be large enough to cause the recursive calls to sum up and overflow the stack. If the list is from some user input then this could be used for a denial of service attack. Thus I see two reasonable choices:
Create a reversed copy of the list and print that.
Reverse the list in place, print it, possibly reverse it back.
The later is interesting if you're working in a memory constrained setting or with large lists.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
struct node {
int value;
struct node * next;
};
void reverse_inplace (struct node ** list) {
assert(list != NULL);
struct node * follow = NULL, * lead = *list;
while (lead != NULL) {
struct node * next = lead->next;
lead->next = follow;
follow = lead;
lead = next;
}
*list = follow;
}
void print (struct node const * head) {
printf("( ");
while (head) {
printf("%d ", head->value);
head = head->next;
}
printf(")");
}
void link (struct node * array, size_t count) {
struct node * follow = NULL;
while (count-->0) {
array[count].next = follow;
follow = &(array[count]);
}
}
void fill (struct node * list, int value, int const step) {
while (list != NULL) {
list->value = value;
value += step;
list = list->next;
}
}
int main () {
size_t const sizes[] = {1, 2, 6};
size_t const num =
sizeof(sizes) / sizeof(sizes[0]);
size_t caseId = 0;
for (; caseId < num; ++caseId) {
struct node * head =
malloc(sizeof(*head) * sizes[caseId]);
printf("Case %zu: List of size %zu\n",
caseId, sizes[caseId]);
link(head, sizes[caseId]);
fill(head, caseId, caseId);
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print (head);
printf(" \n");
reverse_inplace(& head);
free(head);
}
printf("Case %zu: empty list \n", caseId);
struct node * head = NULL;
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print(head);
printf(" \n");
return 0;
}
(Live on ideone)
I am studying for my Algorithms exam and I have an exercise where I need to swap two items of a doubly linked list if a condition is true. (Language: C)
More specifically, I have a list of this kind:
H <-> |prev|Frequency1|VALUE1|next| <-> |prev|Frequency2|VALUE2|next| <-> ... <-> NULL
The frequency field increases every time I search for the relative value. The list must be ordered according to the frequency (in decreasing order, so at the very top there is the most searched item)
The problem is, I am not very good in exchanging pointers, I tried many times to do it but I have no clue. I guess that the problem I am facing is that I don't know how to use a temp item to keep track of what I am doing without loosing data.
I think that the case I have to consider are:
First item of the list
Last item of the list
Item is in the middle of the list.
My attempt, certainly wrong is:
int Search(int x, list* head) {
int contapos = 0;
list* i;
list* aus;
for (i=head; i!=NULL; i = i->next, contapos++)
{
if (i->key == x)
{
i->freq++; // Increase frequency
aus = i->prev;
while ((i->freq > aus->freq))
{ // Keep ordered the frequencies
if (i->next != NULL)
{
i->next->prev = aus;
}
if (aus->prev != NULL)
{
aus->prev->next = i;
}
aus->next = i->next;
i->prev = aus->prev;
aus->prev = i;
i->next = aus;
}
/* Return counter */
return contapos;
}
}
return -1; // In case the item i am searching is not there
}
Thank you in advance for everything!
Edit:
as requested, I am adding the main (and the whole code just to be sure) of the program at the moment
typedef struct _list {
int key;
int freq;
struct _list *next;
struct _list *prev;
} list;
list* head;
list* tail;
void swap(list *lhs, list *rhs) {
list *temp;
temp = lhs->prev;
lhs->prev = rhs->prev;
rhs->prev = temp;
temp = lhs->next;
lhs->next = rhs->next;
rhs->next = temp;
}
void InsertAtTail(int value) {
list *newNode;
newNode = (list*)malloc(sizeof(list));
newNode->key = value;
if(head == NULL)
{
head = newNode;
}
else
{
tail->next = newNode;
newNode->prev = tail;
}
tail = newNode;
tail->next = NULL;
}
int SearchAndIncrement(int x, list** head) {
int contapos = 0;
list* i;
// Let's find the element with the matching key
for (i = *head; i != NULL; i = i->next, contapos++)
if (i->key == x)
break;
// If we did not find the node, return -1 to denote failure.
if (i == NULL)
return -1;
// Increase frequency
i->freq++;
// Move this node forward while the frequency is not in the correct position.
while (i->next && i->prev && (i->freq > i->prev->freq))
swap(i, i->prev);
// The head might have been moved.
while ((*head)->prev != NULL)
(*head) = (*head)->prev;
// Return the original position
return contapos;
}
int main () {
int N;
scanf("%d", &N);
head = NULL;
tail = NULL;
int i, value;
for (i=0; i<N; i++) {
scanf("%d", &value);
InsertAtTail(value);
}
/* Initializing frequencies */
list* aus;
for (aus=head; aus; aus = aus ->next) {
aus->freq = 0;
}
int x, pos;
do {
scanf("%d", &x);
pos = SearchAndIncrement(x, &head);
printf("%d ", pos);
printf("[");
aus = head;
while (aus!=NULL) {
printf("%d ", aus->key);
aus = aus->next;
}
printf("]\n");
} while (pos != -1);
return 0;
}
Let's simplify the problem. The complicated pointer portion is when we are trying to move a node forward in the list. So let's create some functions just for that.
void RemoveNode(list *node) {
if (node->prev)
node->prev->next = node->next;
if (node->next)
node->next->prev = node->prev;
}
void InsertNodeBetween(list *lhs, list *node, list *rhs) {
if (lhs) assert(lhs->next == rhs);
if (rhs) assert(rhs->prev == lhs);
if (lhs) lhs->next = node;
if (rhs) rhs->prev = node;
node->prev = lhs;
node->next = rhs;
}
Once we've done that, then we can more easily talk about the operation that you want to do.
int SearchAndIncrement(int x, list** head) {
int contapos = 0;
list* i;
// Let's find the element with the matching key
for (i = *head; i != NULL; i = i->next, contapos++)
if (i->key == x)
break;
// If we did not find the node, return -1 to denote failure.
if (i == NULL)
return -1;
// Increase frequency
i->freq++;
// Move this node forward while the frequency is not in the correct position.
while (i->next && (i->freq > i->next->freq)) {
list *prev = i->next;
list *next = i->next->next;
RemoveNode(i);
InsertNodeBetween(prev, i, next);
}
// The head might have been moved.
while ((*head)->prev != NULL)
(*head) = (*head)->prev;
// Return the original position
return contapos;
}
Some commentary:
The important thing to note here is that we have the ability to create multiple functions. And we can use those functions to make the amount of the problem that we need to keep in our head at any one time smaller.
When I try to delete every other element in the list using the deleteinst method the method does nothing to the linked list and there are no errors. I'm really not sure why it's not working I've seen the same deleteinst method used in a different program. Maybe it has something to do with the pointers. If I run deleteInst(track.prev, &head); without the while loop the list still remains unchanged.
Please let me know if you have any idea or need more info. Thank you for your time.
int main()
{
node *head;
node *track;
head = ReadNodeList(stdin);
track = LastNode(head); //goes to last node.
while(track != NULL){
int i=0;
//delete every other node
if(i%2 == 1){
deleteInst(track, &head);
}
i++;
track = track->prev;
}
}
void deleteInst(Instruction *victim, Instruction **head){
if(*head == NULL || victim == NULL)
return;
if(*head == victim)
*head = victim->next;
if(victim->next != NULL)
victim->next->prev = victim->prev;
if(victim->prev != NULL)
victim->prev->next = victim->next;
free(victim);
return;
}
One immediately obvious glaring problem: you really don't want to do this:
deleteInst(track, &head);
track = track->prev;
The instant you free that node, you lose the right to access its members. Save it first then recover after the delete:
node *save_prev = track->prev;
deleteInst(track, &head);
track = save_prev;
Another thing I'd check is that the list structure is correct, with something like (only during debug):
static void checkList (node *curr) {
int count = 0;
// PreCon: head->prev must be null.
if (curr != NULL) {
if (curr->prev != NULL) {
puts ("Linked list structure error A!");
exit (1);
}
}
// Check all nodes.
while (curr != NULL) {
// PreCon: curr->prev->next must be curr.
if (curr->prev != NULL) {
if (curr->prev->next != curr) {
puts ("Linked list structure error B!");
exit (1);
}
}
// PreCon: curr->next->prev must be curr.
if (curr->next != NULL) {
if (curr->next->prev != curr) {
puts ("Linked list structure error C!");
exit (1);
}
}
// Move to next and keep count.
curr = curr->next;
count++;
}
// All okay, output success message with size.
printf ("Linked list structure okay, size = %d\n", count);
}
Calling that with checkList (head) will validate that your linked list meets all the validity preconditions, on the off-chance that you may have buggy code elsewhere, such as when creating the list in ReadNodeList().
Beyond that, I suggest single stepping the code in your IDE or debugger after ReadNodeList() to see what it's actually doing. And, if you don't have an IDE/debugger, pepper your source code with lots of lines like:
printf ("DEBUG %d: track = %p\n", __LINE__, track);
and then examine the output of the debug statements to analyse the flow through your program.
Now, if you were to actually do that debugging exercise, it may surprise you to find out that deleteInst never appears to be called, because i seems to be always set to 0.
And the fault of that little problem lies here:
while (track != NULL) {
int i = 0; // <<<<<<<
//delete every other node
if (i%2 == 1) {
deleteInst (track, &head);
}
i++;
track = track->prev;
}
Yes, that's right, you are setting i to 0 every single time through the loop, hence i % 2 will never be equal to 1. You need to initialise i before the loop (and with the undefined behaviour of accessing freed memory removed as well):
int i = 0;
while (track != NULL) {
node *save_prev = track->prev;
//delete every other node
if (i%2 == 1)
deleteInst (track, &head);
i++;
track = save_prev;
}
Doubly linked lists are a whole lot easier to work with if you put a tail on the list during the list initialization. This eliminates most of the mind-numbing corner cases.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
struct node *next;
struct node *prev;
int data;
}
node;
void ShowList( node *head );
void AppendNodeWithData( node *tail, int data );
void RemoveNode( node *item );
int main( void )
{
int i;
node *head, *tail, *item, *temp;
// allocate and initialize the doubly linked list
head = malloc( sizeof(node) );
tail = malloc( sizeof(node) );
if ( !head || !tail )
exit( 1 );
head->next = tail;
head->prev = NULL;
tail->next = NULL;
tail->prev = head;
// add some items to the list
for ( i = 0; i < 20; i++ )
AppendNodeWithData( tail, i );
ShowList( head );
// remove every other item
for ( item = tail->prev; item != NULL && item->prev != NULL; item = temp )
{
temp = item->prev->prev;
RemoveNode( item );
}
ShowList( head );
}
void ShowList( node *head )
{
node *item;
for ( item = head->next; item->next != NULL; item = item->next )
printf( " %d", item->data );
printf( "\n" );
}
void AppendNodeWithData( node *tail, int data )
{
node *item;
if ( (item = malloc( sizeof(node) )) == NULL )
exit( 1 );
item->data = data;
item->prev = tail->prev;
item->next = tail;
tail->prev->next = item;
tail->prev = item;
}
void RemoveNode( node *item )
{
item->next->prev = item->prev;
item->prev->next = item->next;
free( item );
}
I am preparing for a technical interview and I am stuck at writing this program to reverse every k nodes of a linked list.
For example
1->2->3->4->5->6 //Linked List
2->1->4->3->6->5 //Output for k=2
EDIT:
Here is my code. I get only 6->5 as output.
struct node* recrev(struct node* noode,int c)
{
struct node* root=noode,*temp,*final,*prev=NULL;
int count=0;
while(root!=NULL && count<c)
{
count++;
temp=root->link;
root->link=prev;
prev=root;
root=temp;
}
if(temp!=NULL)
noode->link=recrev(temp,c);
else
return prev;
}
Any help is appreciated. Thanks.
EDIT: I tried to implement Eran Zimmerman's Algorithm as below.
struct node* rev(struct node* root,int c)
{
struct node* first=root,*prev,*remaining=NULL;
int count=0;
while(first!=NULL && count<c)
{
count++;
prev=first->link;
first->link=remaining;
remaining=first;
first=prev;
}
return remaining;
}
struct node* recc(struct node* root,int c)
{
struct node* final,*temp,*n=root,*t;
int count=0;
while(n!=NULL)
{
count=0;
temp=rev(n,c);
final=temp;
while(n!=NULL && count<c)
{
printf("inside while: %c\n",n->data); // This gets printed only once
if(n->link==NULL) printf("NULL"); //During first iteration itself NULL gets printed
n=n->link;
final=final->link;
count++;
}
}
final->link=NULL;
return final;
}
Yeah, I have never been a fan of recursion, so here is my shot at it using iteration:
public Node reverse(Node head, int k) {
Node st = head;
if(head == null) {
return null;
}
Node newHead = reverseList(st, k);
st = st.next;
while(st != null) {
reverseList(st, k);
st = st.next;
}
return newHead
}
private Node reverseList(Node head, int k) {
Node prev = null;
Node curr = head;
Node next = head.next;
while(next != null && k != 1){
curr.next = prev;
prev = curr;
curr = next;
next = next.next;
--k;
}
curr.next = prev;
// head is the new tail now.
head.next = next;
// tail is the new head now.
return curr;
}
Here is a pseudo code.
temp = main_head = node.alloc ();
while ( !linked_list.is_empty () )
{
push k nodes on stack
head = stack.pop ();
temp->next = head;
temp = head;
while ( !stack.empty () )
{
temp->next = stack.pop ();
temp = temp->next;
}
}
I have made a demo implementation of this code. Pardon for the messy implementation. This will work for any value of k. Each k sized segment is reversed separately in the inner loop and the different segments are linked with each other in the outer loop before entering the inner one. temp traces the last node of the k sized sublist and head holds the next value of the next sublist, and we link them. An explicit stack is used to do the reversal.
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int a;
struct _node *next;
} node_t;
typedef struct _stack {
node_t *arr[128];
int top;
} stack_t;
void stk_init (stack_t *stk)
{
stk->top = -1;
}
void push (stack_t *stk, node_t *val)
{
stk->arr[++(stk->top)] = val;
}
node_t *pop (stack_t *stk)
{
if (stk->top == -1)
return NULL;
return stk->arr[(stk->top)--];
}
int empty (stack_t *stk)
{
return (stk->top == -1);
}
int main (void)
{
stack_t *stk = malloc (sizeof (stack_t));
node_t *head, *main_head, *temp1, *temp;
int i, k, n;
printf ("\nEnter number of list elements: ");
scanf ("%d", &n);
printf ("\nEnter value of k: ");
scanf ("%d", &k);
/* Using dummy head 'main_head' */
main_head = malloc (sizeof (node_t));
main_head->next = NULL;
/* Populate list */
for (i=n; i>0; i--)
{
temp = malloc (sizeof (node_t));
temp->a = i;
temp->next = main_head->next;
main_head->next = temp;
}
/* Show initial list */
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
stk_init (stk);
/* temp1 is used for traversing the list
* temp is used for tracing the revrsed list
* head is used for tracing the sublist of size 'k' local head
* this head value is used to link with the previous
* sublist's tail value, which we get from temp pointer
*/
temp1 = main_head->next;
temp = main_head;
/* reverse process */
while (temp1)
{
for (i=0; (temp1 != NULL) && (i<k); i++)
{
push (stk, temp1);
temp1 = temp1->next;
}
head = pop (stk);
temp->next = head;
temp = head;
while (!empty (stk))
{
temp->next = pop (stk);
if (temp->next == NULL)
break;
temp = temp->next;
}
}
/* Terminate list with NULL . This is necessary as
* for even no of nodes the last temp->next points
* to its previous node after above process
*/
temp->next = NULL;
printf ("\n");
for (temp = main_head->next; temp != NULL; temp = temp->next)
{
printf ("%d->", temp->a);
}
/* free linked list here */
return 0;
}
I like you recursion, although it may be not the best solution. I can see from your code that you think it deep when you design it. You're just one step away from the answer.
Cause: You forget to return the new root node in your recursion case.
if(temp!=NULL)
noode->link=recrev(temp,c);
// You need return the new root node here
// which in this case is prev:
// return prev;
else
return prev;
I would do something like this:
init curr (node pointer) to point to the beginning of the list.
while end of list is not reached (by curr):
- reverse(curr, k)
- advance curr k times
and reverse is a function that reverses the first k elements starting from curr.
this might not be the most elegant or the most efficient implementation, but it works and is quite simple.
to answer regarding the code you added:
you returned prev, which is constantly being advanced. you should return the beginning of the list.
(I'm assuming this is a singly linked list.) You can keep a temporary pointer (lets call it nodek) and advance it k times in a while loop. This will take O(k). Now you have a pointer to the start of the list and to the last element of the sublist. To reverse here, you remove from head which is O(1) and add to nodek which is O(1). Do this for all elements, so this is O(k) again. Now update root to nodek, and run the while loop on nodek again (to get the new position of nodek) and repeat this whole process again. Remember to do any error checking along the way.
This solution will run at O(n) with only O(1) extra space.
The following solution uses extra space for storing pointers,and reverses each chunk of list separately. Finally,the new list is built. When I tested, this seemed to cover the boundary conditions.
template <typename T>
struct Node {
T data;
struct Node<T>* next;
Node() { next=NULL; }
};
template <class T>
void advancePointerToNextChunk(struct Node<T> * & ptr,int & k) {
int count =0;
while(ptr && count <k ) {
ptr=ptr->next;
count ++;
}
k=count;}
/*K-Reverse Linked List */
template <class T>
void kReverseList( struct Node<T> * & head, int k){
int storeK=k,numchunk=0,hcount=0;
queue < struct Node<T> *> headPointerQueue;
queue <struct Node<T> *> tailPointerQueue;
struct Node<T> * tptr,*hptr;
struct Node<T> * ptr=head,*curHead=head,*kReversedHead,*kReversedTail;
while (ptr) {
advancePointerToNextChunk(ptr,storeK);
reverseN(curHead,storeK,kReversedHead,kReversedTail);
numchunk++;
storeK=k;
curHead=ptr;
tailPointerQueue.push(kReversedTail),headPointerQueue.push(kReversedHead);
}
while( !headPointerQueue.empty() || !tailPointerQueue.empty() ) {
if(!headPointerQueue.empty()) {
hcount++;
if(hcount == 1) {
head=headPointerQueue.front();
headPointerQueue.pop();
}
if(!headPointerQueue.empty()) {
hptr=headPointerQueue.front();
headPointerQueue.pop();
}
}
if( !tailPointerQueue.empty() ) {
tptr=tailPointerQueue.front();
tailPointerQueue.pop();
}
tptr->next=hptr;
}
tptr->next=NULL;}
template <class T> void reverseN(struct Node<T> * & head, int k, struct Node<T> * & kReversedHead, structNode<T> * & kReversedTail ) {
struct Node<T> * ptr=head,*tmp;
int count=0;
struct Node<T> *curr=head,*nextNode,*result=NULL;
while(curr && count <k) {
count++;
cout <<"Curr data="<<curr->data<<"\t"<<"count="<<count<<"\n";
nextNode=curr->next;
curr->next=kReversedHead;
kReversedHead=curr;
if(count ==1 ) kReversedTail=kReversedHead;
curr=nextNode;
}}
public class ReverseEveryKNodes<K>
{
private static class Node<K>
{
private K k;
private Node<K> next;
private Node(K k)
{
this.k = k;
}
}
private Node<K> head;
private Node<K> tail;
private int size;
public void insert(K kk)
{
if(head==null)
{
head = new Node<K>(kk);
tail = head;
}
else
{
tail.next = new Node<K>(kk);
tail = tail.next;
}
size++;
}
public void print()
{
Node<K> temp = head;
while(temp!=null)
{
System.out.print(temp.k+"--->");
temp = temp.next;
}
System.out.println("");
}
public void reverse(int k)
{
head = reverseK(head, k);
}
Node<K> reverseK(Node<K> n, int k)
{
if(n==null)return null;
Node<K> next=n, c=n, previous=null;
int count = 0;
while(c!=null && count<k)
{
next=c.next;
c.next=previous;
previous=c;
c=next;
count++;
}
n.next=reverseK(c, k);
return previous;
}
public static void main(String[] args)
{
ReverseEveryKNodes<Integer> r = new ReverseEveryKNodes<Integer>();
r.insert(10);
r.insert(12);
r.insert(13);
r.insert(14);
r.insert(15);
r.insert(16);
r.insert(17);
r.insert(18);
r.print();
r.reverse(3);
r.print();
}
}