C - deleting node in doubly linked list - c

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 );
}

Related

Removing unique elements in a doubly linked list in C

I need a little help removing unique characters in a doubly linked list in C. So here's the logic I tried implementing: I counted the occurrence of each character in the doubly linked list. If it's occurrence is 1 time, then it is unique element and needs to be deleted. I'll be repeating the process for all elements. But my code in remove_unique_dll() function isn't working properly, please help me fix it. Here's my code-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char data;
struct node *next;
struct node *prev;
};
struct node *head, *tail = NULL; //Represent the head and tail of the doubly linked list
int len;
void addNode(char data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node)); //Create new node
newNode->data = data;
if (head == NULL)
{ //If dll is empty
head = tail = newNode; //Both head and tail will point to newNode
head->prev = NULL; //head's previous will point to NULL
tail->next = NULL; //tail's next will point to NULL, as it is the last node of the list
}
else
{
tail->next = newNode; //newNode will be added after tail such that tail's next points to newNode
newNode->prev = tail; //newNode's previous will point to tail
tail = newNode; //newNode will become new tail
tail->next = NULL; //As it is last node, tail's next will point to NULL
}
}
void remove_unique_dll()
{
struct node *current = head;
struct node *next;
struct node *prev;
int cnt;
while (current != NULL)
{
next = current->next;
cnt = 1;
//printf("!%c ",next->data);
while (next != NULL)
{
if (next->data == current->data)
{
cnt += 1;
next = next->next;
}
else
next = next->next;
//printf("#%c %d %c\n",next->data,cnt,current->data);
}
if (cnt == 1)
{
prev = current->prev;
//printf("#%c %d",prev->data,cnt);
if (prev == NULL)
{
head = next;
}
else
{
prev->next = next;
}
if (next == NULL)
{
tail = prev;
}
else
{
next->prev = prev;
}
}
current = current->next;
//printf("#%c ",current->data);
}
head = current;
}
void display()
{
struct node *current = head; //head the global one
while (current != NULL)
{
printf("%c<->", current->data); //Prints each node by incrementing pointer.
current = current->next;
}
printf("NULL\n");
}
int main()
{
char s[100];
int i;
printf("Enter string: ");
scanf("%s", s);
len = strlen(s);
for (i = 0; i < len; i++)
{
addNode(s[i]);
}
printf("Doubly linked list: \n");
display();
remove_unique_dll();
printf("Doubly linked list after removing unique elements: \n");
display();
return 0;
}
The output is like this-
If you uncomment the printf() statements inside remove_unique_dll() you'll notice that no code below inner while loop is being executed after inner while loop ends. What's the issue here and what's the solution?
Sample input- aacb
Expected output- a<->a<->NULL
Some issues:
You shouldn't assign head = current at the end, because by then current is NULL
The next you use in the deletion part is not the successor of current, so this will make wrong links
As you progress through the list, every value is going to be regarded as unique at some point: when it is the last occurrence, you'll not find a duplicate anymore, as your logic only looks ahead, not backwards.
When you remove a node, you should free its memory.
Not a big issue, but there is no reason to really count the number of duplicates. Once you find the first duplicate, there is no reason to look for another.
You should really isolate the different steps of the algorithm in separate functions, so you can debug and test each of those features separately and also better understand your code.
Also, to check for duplicates, you might want to use the following fact: if the first occurrence of a value in a list is the same node as the last occurrence of that value, then you know it is unique. As your list is doubly linked, you can use a backwards traversal to find the last occurrence (and a forward traversal to find the first occurrence).
Here is some suggested code:
struct node* findFirstNode(char data) {
struct node *current = head;
while (current != NULL && current->data != data) {
current = current->next;
}
return current;
}
struct node* findLastNode(char data) {
struct node *current = tail;
while (current != NULL && current->data != data) {
current = current->prev;
}
return current;
}
void removeNode(struct node *current) {
if (current->prev == NULL) {
head = current->next;
} else {
current->prev->next = current->next;
}
if (current->next == NULL) {
tail = current->prev;
} else {
current->next->prev = current->prev;
}
free(current);
}
void remove_unique_dll() {
struct node *current = head;
struct node *next;
while (current != NULL)
{
next = current->next;
if (findFirstNode(current->data) == findLastNode(current->data)) {
removeNode(current);
}
current = next;
}
}
You have at least three errors.
After counting the number of occurrences of an item, you use next in several places. However, next has been used to iterate through the list. It was moved to the end and is now a null pointer. You can either reset it with next = current->next; or you can change the places that use next to current->next.
At the end of remove_unique_dll, you have head=current;. There is no reason to update head at this point. Whenever the first node was removed from the list, earlier code in remove_unique_dll updated head. So it is already updated. Delete the line head=current;.
That will leave code that deletes all but one occurrence of each item. However, based on your sample output, you want to leave multiple occurrences of items for which there are multiple occurrences. For that, you need to rethink your logic in remove_unique_dll about deciding which nodes to delete. When it sees the first a, it scans the remainder of the list and sees the second, so it does not delete the first a. When it sees the second a, it scans the remainder of the list and does not see a duplicate, so it deletes the second a. You need to change that.
Let's consider your code step by step.
It seems you think that in this declaration
struct node *head, *tail = NULL; //Represent the head and tail of the doubly linked list
the both pointers head and tail are explicitly initialized by NULL. Actually only the pointer tail is explicitly initialized by NULL. The pointer head is initialized implicitly as a null pointer only due to placing the declaration in file scope. It to place such a declaration in a block scope then the pointer head will be uninitialized.
Instead you should write
struct node *head = NULL, *tail = NULL; //Represent the head and tail of the doubly linked list
Also it is a very bad approach when the functions depend on these global variables. In this case you will be unable to have more than one list in a program.
Also the declaration of the variable len that is used only in main as a global variable
int len;
also a bad idea. And moreover this declaration is redundant.
You need to define one more structure that will contain pointers head and tail as data members as for example
struct list
{
struct node *head;
struct node *tail;
};
The function addNode can invoke undefined behavior when a new node can not be allocated
void addNode(char data)
{
struct node *newNode = (struct node*) malloc(sizeof(struct node)); //Create new node
//...
You should check whether a node is allocated successfully and only in this case change its data members. And you should report the caller whether a node is created or not.
So the function should return an integer that will report an success or failure.
In the function remove_unique_dll after this while loop
while (next != NULL)
{
if (next->data == current->data)
{
cnt += 1;
next = next->next;
}
else
next = next->next;
//printf("#%c %d %c\n",next->data,cnt,current->data);
}
if cnt is equal to 1
if (cnt == 1)
//..
then the pointer next is equal to NULL. And using the pointer next after that like
if (prev == NULL)
{
head = next;
}
else
{
prev->next = next;
}
is wrong.
Also you need to check whether there is a preceding node with the same value as the value of the current node. Otherwise you can remove a node that is not a unique because after it there are no nodes with the same value.
And this statement
head = current;
does not make sense because after the outer while loop
while (current != NULL)
the pointer current is equal to NULL.
Pay attention that the function will be more useful for users if it will return the number of removed unique elements.
Here is a demonstration program that shows how the list and the function remove_unique_dll can be defined.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char data;
struct node *next;
struct node *prev;
};
struct list
{
struct node *head;
struct node *tail;
};
int addNode( struct list *list, char data )
{
struct node *node = malloc( sizeof( *node ) );
int success = node != NULL;
if (success)
{
node->data = data;
node->next = NULL;
node->prev = list->tail;
if (list->head == NULL)
{
list->head = node;
}
else
{
list->tail->next = node;
}
list->tail = node;
}
return success;
}
size_t remove_unique_dll( struct list *list )
{
size_t removed = 0;
for ( struct node *current = list->head; current != NULL; )
{
struct node *prev = current->prev;
while (prev != NULL && prev->data != current->data)
{
prev = prev->prev;
}
if (prev == NULL)
{
// there is no preceding node with the same value
// so the current node is possibly unique
struct node *next = current->next;
while (next != NULL && next->data != current->data)
{
next = next->next;
}
if (next == NULL)
{
// the current node is indeed unique
struct node *to_delete = current;
if (current->prev != NULL)
{
current->prev->next = current->next;
}
else
{
list->head = current->next;
}
if (current->next != NULL)
{
current->next->prev = current->prev;
}
else
{
list->tail = current->prev;
}
current = current->next;
free( to_delete );
++removed;
}
else
{
current = current->next;
}
}
else
{
current = current->next;
}
}
return removed;
}
void display( const struct list *list )
{
for (const node *current = list->head; current != NULL; current = current->next)
{
printf( "%c<->", current->data );
}
puts( "null" );
}
int main()
{
struct list list = { .head = NULL, .tail = NULL };
const char *s = "aabc";
for (const char *p = s; *p != '\0'; ++p)
{
addNode( &list, *p );
}
printf( "Doubly linked list:\n" );
display( &list );
size_t removed = remove_unique_dll( &list );
printf( "There are removed %zu unique value(s) in the list.\n", removed );
printf( "Doubly linked list after removing unique elements:\n" );
display( &list );
}
The program output is
Doubly linked list:
a<->a<->b<->c<->null
There are removed 2 unique value(s) in the list.
Doubly linked list after removing unique elements:
a<->a<->null
You will need at least to write one more function that will free all the allocated memory when the list will not be required any more.

Inserting at tail of linked list

I am writing a program to become familiar with linked lists and when attempting to insert a new link at the end of the list the value is seemingly not stored. I assume it has to do with a local variable not saving to the variable passed into the function.
The function in question:
int insertAtTail(int intBeingAdded, List *userList){
while(userList->next != NULL){
userList = userList->next;
}
List *newLink = (List *)malloc(sizeof(List));
userList->next = newLink;
newLink->next = NULL;
newLink->value = intBeingAdded;
return 1;
}
The entirety of the file:
#include "stdio.h"
#include "stdlib.h"
typedef struct list{
int value;
struct list * next;
} List;
List * initIntegerList(void);
int insertAtHead(int intBeingAdded, List *userList);
int insertAtTail(int intBeingAdded, List *userList);
void printList(List *userList);
int main(void){
List *myList;
myList = initIntegerList();
insertAtHead(2, myList);
insertAtHead(1, myList);
insertAtTail(6, myList);
printList(myList);
freeList(myList);
}
List * initIntegerList(void){
List * listPointer = (List *)malloc(sizeof(List));
if(listPointer != NULL){
listPointer->next = NULL;
return listPointer;
}else{
printf("Memory not available for allocation\n");
return listPointer;
}
}
int insertAtHead(int intBeingAdded, List *userList){
List *previousHead = (List *)malloc(sizeof(List));
if(previousHead != NULL){
previousHead->value = intBeingAdded;
previousHead->next = userList->next;
userList->next = previousHead;
return 1;
}
return 0;
}
int insertAtTail(int intBeingAdded, List *userList){
while(userList->next != NULL){
userList = userList->next;
}
List *newLink = (List *)malloc(sizeof(List));
userList->next = newLink;
newLink->next = NULL;
newLink->value = intBeingAdded;
return 1;
}
void printList(List *userList){
printf("Values in list: ");
List *currentLink = userList;
while(currentLink->next != NULL){
printf(" %d", currentLink->value);
currentLink = currentLink->next;
}
printf("\n");
}
The output I am seeing is only 0,1,2 are stored and the 6 is not making it.
When you print the list:
while(currentLink->next != NULL){
You stop when you reach the last node and don't print its contents. You instead want:
while(currentLink != NULL){
Also, your list has a dummy entry at the start of the list. When you print the list, you want to skip that one.
List *currentLink = userList->next;
Your list is built such a way that the head node does not contain a value. It is a dummy node. On the other hand, the last node always contains the data member next equal to NULL.
So this condition in the function printList
while(currentLink->next != NULL){
does not output the value of the last node.
The function can be written like
void printList( const List *userList )
{
printf("Values in list: ");
if ( userList != NULL )
{
for ( const List *currentLink = userList->next;
currentLink != NULL;
currentLink = currentLink->next )
{
printf( " %d", currentLink->value );
}
}
printf("\n");
}
Pay attention to that it is a bad idea to have a dummy node as a head node. The head node should be just set to NULL.

Why position 0 in delete node does not work?

Im new to c programming. I wanted to create a linked list from a given file and then randomly get a node from linked list then delete that node.
So the code works great but for the position 0 in linked list does not work.
Please help me
here's the code:
typedef struct node{
int *name;
struct node *next;
}node;
delete node:
void deleteNode(node **head_ref, int position){
if(*head_ref == NULL){
return;
}
node * temp = *head_ref;
if(position == 0)
{
*head_ref = (*head_ref)->next;
return;
}
int h;
for(h=0 ; temp!=NULL && h<position-1 ; h++){
temp = temp->next;
}
if(temp == NULL || temp->next == NULL)
return;
node * next = temp->next->next;
free(temp->next);
temp->next = next;}
getting random node:
void RandomFromList(node *head){
// IF list is empty
if (head == NULL){
return -1;
}
word = head->name;
// Iterate from the (k+1)th element to nth element
node *current = head;
int n;
for (n=2; current!=NULL; n++)
{
// change result with probability 1/n
if (rand() % n == 0)
word = current->name;
// Move to next node
current = current->next;
}
sprintf(words , "%s" , word);
deleteNode(&head , search(head , word));
printf("Randomly selected key is %s\n", words);}
and the file Reader:
node* fileReader(FILE *file){
node *t = malloc(sizeof(node));
char TopicName[20];
int fileRead = fscanf(file,"%s",TopicName);
if(fileRead != EOF){
t->name = strdup(TopicName);
tedad++;
t->next = fileReader(file);
}
if(fileRead == EOF) {
return NULL;
}
return t;}
EDIT:
When the code run's and when the position randomly got 0 the 0 position of linked list doesn't delete and continues with that node in linked list.
EDIT2:I changed my delete node and it works well without any problem, thank you guys!
node* deleteNode(node* head, unsigned i){
node* next;
if(head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next)
: (head->next = delete_at_index(next, i - 1), head);
}
The major logical problem I see with your delete function is that it is void, i.e. it returns nothing. This is fine if the node being deleted is in the middle (or end) of the list, because the head does not change. But for the case of deleting the head, the caller might expect that his reference would then point to the next node (or null, if a list of one element) after making the call. Consider this code:
node* deleteNode (node *head_ref, int position)
{
// passing in a NULL list returns NULL
if (head_ref == NULL) {
{
return NULL;
}
// deleting the first element returns the second element as the new head
node* temp = head_ref;
if (position == 0)
{
node* ret = temp->next;
free(head_ref);
return ret;
}
// otherwise walk down the list to one before the deletion position
for (int h=0; temp != NULL && h < position-1; h++) {
temp = temp->next;
}
// if found, delete the node at the desired position
if (temp != NULL && temp->next == NULL) {
node* next = temp->next->next;
free(temp->next);
temp->next = next;
}
// for cases other than deleting the head, just return the current
// (unmodified) head
return head_ref;
}
This isn't related to your problem, but don't forget to free the memory:
node * temp = *head_ref;
if(position == 0)
{
*head_ref = temp->next;
free(temp); // <--------
return;
}
Also, you already have a pointer (temp) to *head_ref, it looks cleaner to me to just use that pointer instead of dereferencing head_ref again.
void deleteNode(node **head_ref, int pos){
node *del;
for ( ; *head_ref; head_ref = &(*head_ref)->next) {
if (pos-- <= 0) break;
}
if (!*head_ref) return; // Reached end of list: nothing found
del = *head_ref;
*head_ref = del->next;
free(del);
return;
}
If you want to keep deleteNode void, then the problem is with your RandomFromList function. You are just changing the * head that exists in the function body not the pointer you passed to the function, so it's still pointing to the previous node.
It's because that pointers are passed by value (copied) like other things in C.
Try making RandomFromList return the head pointer.
P.s. I think you also have some memory leaks in the delete function.

ANSI C S-Linked List - deleteLast() not functioning correctly

When trying to run my deleteLast() function twice (to get an empty list) on a linked list with two nodes, I am running into a problem. The code compiles and runs, but when I call traverse() on my empty linked list, I get an infinite while loop, and I cannot determine why.
Oddly enough, if I call deleteFirst() twice instead of deleteLast(), the program runs and terminates properly.
Below is the code for my methods:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
struct NODE
{
struct NODE *link;
int value;
};
typedef struct NODE Node;
/* Deletes the first item in the list and returns next item */
Node *deleteFirst(Node **ptrToHeadPtr)
{
Node *current;
// If list is empty do nothing
if (*ptrToHeadPtr == NULL)
return NULL;
else
{
current = *ptrToHeadPtr;
*ptrToHeadPtr = current->link;
free(current);
}
return *ptrToHeadPtr;
}
/* Inserts a new Node to the end of the list and returns it */
Node *insertLast(Node **ptrToHeadPtr, int val)
{
Node *current, *lastNode;
lastNode = (Node *)malloc( sizeof (Node) );
// Check if malloc was successful
if(!lastNode) return NULL;
lastNode->value = val;
lastNode->link = NULL;
if (*ptrToHeadPtr == NULL)
*ptrToHeadPtr = lastNode;
else
{
current = *ptrToHeadPtr;
// Walk to the end of the list
while(current->link != NULL)
current = current->link;
// Insert new item at the end of the list
current->link = lastNode;
}
return lastNode;
}
/* Deletes the last Node in the list and returns*/
Node *deleteLast(Node **ptrToHeadPtr)
{
Node *current, *previous;
/* If list is empty do nothing */
if (*ptrToHeadPtr == NULL)
return NULL;
current = *ptrToHeadPtr;
previous = NULL;
/* If list has one item delete it and return NULL */
if (current->link == NULL)
{
*ptrToHeadPtr == NULL;
free(current);
return NULL;
}
else
{
/* Walk to the end of the list */
while (current->link != NULL)
{
previous = current;
current = current->link;
}
previous->link = NULL;
free(current);
return previous;
}
}
/* Traverses the list, printing the value of each Node */
void traverse(Node*p)
{
while( p!= NULL )
{
printf("%d ",p->value);
p=p -> link;
}
}
/* Walks through the linked list, freeing memory of each Node */
void freeList(Node *p)
{
Node *temp;
while( p != NULL )
{
temp = p;
p = p-> link;
free(temp);
}
}
int main()
{
Node *headPtr = NULL;
insertLast( &headPtr, 33 );
insertLast( &headPtr, 35 );
traverse(headPtr);
printf("\n");
deleteFirst ( &headPtr );
traverse(headPtr);
printf("\n");
deleteLast ( &headPtr );
traverse(headPtr);
freeList(headPtr);
return 1;
}
In your deleteLast() function (They're called functions in C, just so you know, not methods. Not trying to sound snarky.)
/* If list has one item delete it and return NULL */
if (current->link == NULL)
{
*ptrToHeadPtr == NULL; // CHANGE THIS TO =, NOT ==
free(current);
return NULL;
}
edit: Just like the above poster suggested, you should definitely compile with -Wall (the W is case sensitive, must be capitalized.) It would have caught this.

Rotating a Linked List C

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;
}

Resources