Rotate a linked list - c

I want to rotate a linked list that contains a number. 123 should be rotated to 231. The function created 23 but the last character stays empty, why?
typedef struct node node;
struct node{
char digit;
node* p;
};
void rotate(node** head){
node* walk= (*head);
node* prev= (*head);
char temp= walk->digit;
while(walk->p!=NULL){
walk->digit=walk->p->digit;
walk= walk->p;
}
walk->digit=temp;
}
How I create the list:
node* convert_to_list(int num){
node * curr, * head;
int i=0,length=0;
char *arr=NULL;
head = NULL;
length =(int) log10(((double) num))+1;
arr =(char*) malloc((length)*sizeof(char)); //allocate memory
sprintf (arr, "%d" ,num); //(num, buf, 10);
for(i=length;i>=0;i--) {
curr = (node *)malloc(sizeof(node));
(curr)->digit = arr[i];
(curr)->p = head;
head = curr;
}
curr = head;
return curr;
}

Your linked list actually has 4 elements.
You should change this line:
for(i = length; i >= 0 ; i--) {
to:
for(i = length - 1; i >= 0; i--) {
because with the former line you're going out of the array (you're accessing arr[length] on the first iteration).
With this change your rotate function works correctly.

You can solve most problems by breaking them down into simpler ones.
Here, I'd write your rotate as follows:
void rotate(node **list) {
node *head = pop_head(list);
push_at_end(list, head);
}
node *pop_head(node **list) {
assert(*list);
node *head = *list;
*list = head->p;
head->p = 0;
return head;
}
void push_at_end(node **list, node *head) {
node *end = get_end(*list);
if (!end) {
*list = head;
} else {
end->p = head;
}
}
node *get_end(node *head) {
node *last = 0;
while (head) {
last = head;
head = head->p;
}
return last;
}

The problem with your question is that the list is stored backwards, and you have a pointer to previous, instead next. This should have been part of the question (it took me a while to understand that).
Actually, you use head when probably tail would have been better. You should consider storing a pointer to the actual head, and avoid this way copying. In that case, you would only need to adjust pointers. If rotation is going to be a common task, then keeping and updating an extra pointer, may be in a list struct, would pay the effort (could change the task from O(n) to O(1)).
struct _list {
node * tail;
node * head;
};
typedef struct _list list;
In any case, the problem with your rotate function is that you are starting with walk and prev at the same node, head.
void rotate(node** head){
node* walk= (*head);
node* prev=(*head)->p;
char temp= walk->digit;
while(prev!=NULL){
walk->digit=prev->digit;
walk= prev;
prev = prev->p;
}
walk->digit=temp;
}

I have written the code for linked list rotation by k nodes in c++. It worked for me perfectly. If you pass k as 1, it will rotate the liked list by 1 node and here it solves the given problem. If you want to rotate the linked list by k nodes, it will still work fine. Please find it below.
Header file :
public:
typedef struct node {
int data;
node *next;
} *Node;
Node head;
void rotateByk(int k);
Following code is for .cpp file.
void DList::rotateByk(int k){
Node current = head;
Node kthNode;
int count = 1;
while(count<=k && current!=NULL){
kthNode = current;
current = current->next;
count++;
}
Node kthNextNode = current;
while(current->next!=NULL){
current = current->next;
}
current->next = head;
head = kthNextNode;
kthNode->next = NULL;
Node printNode = head;
while(printNode!=NULL){
cout << printNode->data << "\t";
printNode = printNode->next;
}
}
Pass k as argument in main method for linked list d1.
d1.rotateByk(1);
Please let me know if you have any queries.

Related

C: Problems with Reversing a linked list

I'm writing a program to create a linked list(a node), then reverse it. The linked list contains data and the address of the next.
typedef struct node{
int data;
struct node *next;
}node;
Firstly, I create the linked list.
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
After that, i create a function to print these data. (i called it PrintNode)
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
Finally, a function created to reverse the linked list.
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
It's my full program.
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}node;
struct node *Insert_value(int dataInput,node* head);
struct node * Reversing(node **head);
void PrintNode(node *head);
main()
{
node *head = NULL;
int i=0,dataInput;
while(i!=5)
{
printf("input your elements: ");
scanf("%d",&dataInput);
head = Insert_value(dataInput,head);
i++;
}
PrintNode(head);
head = Reversing(&head);
PrintNode(head);
}
struct node *Insert_value(int dataInput,node* head)
{
node *new_node=NULL;
new_node = malloc(sizeof(node));
new_node -> next = head;
new_node -> data = dataInput;
head = new_node;
return head;
}
struct node* Reversing(node **head)
{
node *current, *previous, *first;
current = previous = first = *head;
first = first->next->next;
current = current->next;
previous ->next = NULL;
current->next = previous;
while(first != NULL)
{
previous = current;
current = first;
first = first -> next;
previous->next = current;
}
return current;
}
void PrintNode(node* head)
{
while(head!= NULL)
{
printf("%d\t",head->data);
head= head->next;
}
printf("\n");
}
After debugging lots of times, I know that these functions are fine. However, after the reverse function, the address of the next node of the head variable is NULL. Can you explain and give me some pieces of advice?
The one line change that will solve your problem will be (you visualized it a bit wrong).
current->next =previous;
in place of
previous->next = current;
Your code will blowup for single element linked list. Add a proper check for that in the function Reversing(). In case there is single element first->next will be NULL. But you wrote first->next->next which will be undefined behavior in case first->next is NULL.
In earlier case you were just creating a linked list in Reversing() with the links unchanged but head was pointing to the last node. So the next of it was NULL.
Modify Reversing such that new nodes are appended at the end. When going through the list, you need to save the next node ahead of time (node *next = current->next)
struct node* Reversing(node **head)
{
node *current = *head;
node *reverse = NULL;
while(current)
{
node *next = current->next;
if(!reverse)
{
reverse = current;
reverse->next = NULL;
}
else
{
current->next = reverse;
}
reverse = current;
current = next;
}
return reverse;
}

Returning a pointer to the beginning of a linked list after adding nodes?

struct node {
struct node *next;
int num;
} Node;
Node *insert(int i) {
Node *head;
for (int c = 0; c < i; c++) {
head = malloc(sizeof(Node));
head.num = i;
head = head->next;
}
}
The insert function is supposed to create a linked list and add numbers from 0 to i to that linked list. However, it is also supposed to return a pointer to the beginning of the list/the list itself and I can't seem to figure out how to do it. I've tried to make a pointer and set it equal to head after adding the first node, but it only returns the first node and not the entire list. Can someone please help? Thanks.
You probably want to remember the previous node, so you can assign its next pointer. When you add a node, set its next pointer to the old head, and it now becomes the new head of the list. Which you can just return after the last iteration of the loop.
Node *insert(int i) {
Node *head, *prev = NULL;
for (int c = 0; c < i; c++) {
head = malloc(sizeof(Node));
head->num = i;
head->next = prev;
prev = head;
}
return head;
}
Update: to insert each new element at the end of the list, you need a bit more bookkeeping:
Node *insert(int i) {
Node *last_node = NULL;
Node *first_node = NULL;
for (int c = 0; c < i; c++) {
Node *node = malloc(sizeof(Node));
node->num = i;
node->next = NULL;
if (!last_node) {
// Remember the first node, so we can return it.
first_node = node;
}
else {
// Otherwise, append to the existing list.
last_node->next = node;
}
last_node = node;
}
return first_node;
}
It is as simple as introducing another variable. You currently have head to track the head of the list; add another to track the tail of the list:
struct node {
struct node *next;
int num;
} Node;
Node *insert(int i) {
Node *head;
Node *tail;
head = malloc(sizeof(Node));
head.num = 0;
tail = head;
for (int c = 1; c < i; c++) {
// allocate a new node at the end of the list:
tail->next = malloc(sizeof(Node));
// set "tail" to point to the new tail node:
tail = tail->next;
tail->num = c;
}
return head;
}
You could also add a special case for i == 0, if necessary.
By the way - and I realise this is possibly a task given to you as an exercise - but insert is a terrible name for a function that actually creates and fills an entirely new list.

Inserting into a linked list not working properly

I want to add a insert method for my linked list that would insert onto what's already in the linked list (append values).
Here's my code now:
struct node {
char value;
struct node *next;
};
typedef struct node item;
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
void InsertChar(char s) {
item *curr, *head;
head = NULL;
curr = (item *)malloc(sizeof(item));
curr->value = s;
curr->next = head;
head = curr;
while(curr) {
printf("%c", curr->value);
curr = curr->next;
}
printf("\n");
}
The problem is that in the console it prints
a
b
c
I need it to print something more like
a
ab
abc
After calling the 3 InsertChar methods in main().
How can I do this?
Your problem is that the head is declared locally in the function, and when you leave the function, you loose it. When you come to the function again, you create it from scratch, etc.
So you need to pass head as an argument to your InsertChar function.
Also, if you want to see a, ab, abc output, you need to add elements to the tail of your list, rather than to the head as you do it now. In order to achieve that, you either need to store a separate pointer for tail or every time traverse to the last element.
You have to be keeping track of the head of your list. E.g.:
struct node {
char value;
struct node *next;
};
typedef struct node item;
item* head = NULL;
item* curr = NULL;
void InsertChar(char s) {
item* c = (item *)malloc(sizeof(item));
c->value = s;
c->next = NULL;
if (head)
curr->next = c;
else
head = c;
curr = c;
for (c = head; c; c = c->next)
printf("%c", c->value);
printf("\n");
}
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
This outputs:
a
ab
abc
There are two problems :
The list's is redefined each time the function is invoked.
you should start from the head of the list when you access the list's elements
This should fix your problem :
struct node {
char value;
struct node *next;
};
typedef struct node item;
item * head = NULL; // global
void main() {
InsertChar('a');
InsertChar('b');
InsertChar('c');
}
void InsertChar(char s) {
item *curr, *temp;
curr = (item *)malloc(sizeof(item));
curr->value = s;
curr->next = head;
head = curr;
temp = head;
while(temp) {
printf("%c", temp->value);
temp = temp->next;
}
printf("\n");
}

C: How to free nodes in the linked list?

How will I free the nodes allocated in another function?
struct node {
int data;
struct node* next;
};
struct node* buildList()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
}
I call the buildList function in the main()
int main()
{
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
}
I want to free head, second and third variables.
Thanks.
Update:
int main()
{
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
}
Both prints 2. Shouldn't calling free(h) remove h. If so why is that h->next->data available, if h is free. Ofcourse the 'second' node is not freed. But since head is removed, it should be able to reference the next element. What's the mistake here?
An iterative function to free your list:
void freeList(struct node* head)
{
struct node* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
What the function is doing is the follow:
check if head is NULL, if yes the list is empty and we just return
Save the head in a tmp variable, and make head point to the next node on your list (this is done in head = head->next
Now we can safely free(tmp) variable, and head just points to the rest of the list, go back to step 1
Simply by iterating over the list:
struct node *n = head;
while(n){
struct node *n1 = n;
n = n->next;
free(n1);
}
One function can do the job,
void free_list(node *pHead)
{
node *pNode = pHead, *pNext;
while (NULL != pNode)
{
pNext = pNode->next;
free(pNode);
pNode = pNext;
}
}
struct node{
int position;
char name[30];
struct node * next;
};
void free_list(node * list){
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
{
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
}
}
You could always do it recursively like so:
void freeList(struct node* currentNode)
{
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
}

Elegant implementation of circular singly-linked list in C?

Going through classic data structures and have stopped on linked lists.Just implemented a circular singly-linked list, but I'm under overwhelming impression that this list could be expressed in a more elegant manner, remove_node function in particular.
Keeping in mind efficiency and code readability, could anybody present a more concise and efficient solution for singly-linked circular list?
#include <stdio.h>
#include <stdlib.h>
struct node{
struct node* next;
int value;
};
struct list{
struct node* head;
};
struct node* init_node(int value){
struct node* pnode;
if (!(pnode = (struct node*)malloc(sizeof(struct node)))){
return NULL;
}
else{
pnode->value = value;
}
return pnode;
}
struct list* init_list(){
struct list* plist;
if (!(plist = (struct list*)malloc(sizeof(struct list)))){
return NULL;
}
plist->head = NULL;
return plist;
}
void remove_node(struct list*a plist, int value){
struct node* current, *temp;
current = plist->head;
if (!(current)) return;
if ( current->value == value ){
if (current==current->next){
plist->head = NULL;
free(current);
}
else {
temp = current;
do {
current = current->next;
} while (current->next != plist->head);
current->next = plist->head->next;
plist->head = current->next;
free(temp);
}
}
else {
do {
if (current->next->value == value){
temp = current->next;
current->next = current->next->next;
free(temp);
}
current = current->next;
} while (current != plist->head);
}
}
void print_node(struct node* pnode){
printf("%d %p %p\n", pnode->value, pnode, pnode->next);
}
void print_list(struct list* plist){
struct node * current = plist->head;
if (!(current)) return;
if (current == plist->head->next){
print_node(current);
}
else{
do {
print_node(current);
current = current->next;
} while (current != plist->head);
}
}
void add_node(struct node* pnode,struct list* plist){
struct node* current;
struct node* temp;
if (plist->head == NULL){
plist->head = pnode;
plist->head->next = pnode;
}
else {
current = plist->head;
if (current == plist->head->next){
plist->head->next = pnode;
pnode->next = plist->head;
}
else {
while(current->next!=plist->head)
current = current->next;
current->next = pnode;
pnode->next = plist->head;
}
}
}
Take a look at the circular linked list in the Linux kernel source: http://lxr.linux.no/linux+v2.6.36/include/linux/list.h
Its beauty derives from the fact that you don't have a special struct for your data to fit in the list, you only have to include the struct list_head * in the struct you want to have as a list. The macros for accessing items in the list will handle the offset calculation to get from the struct list_head pointer to your data.
A more verbose explanation of the linked list used in the kernel can be found at kernelnewbies.org/FAQ/LinkedLists (Sorry, I dont have enough karma to post two hyperlinks).
Edit: Well, the list is a double-linked list and not a single-linked one like you have, but you could adopt the concept and create your own single-linked list.
List processing (particularly of circular lists) gets way easier when you treat the list head like an element of the list (a so-called "sentinel"). A lot of special cases just disappear. You can use a dummy node for the sentinel, but if the next pointer is first in the struct, you don't need to do even that. The other big trick is to keep a pointer to the next pointer of the previous node (so you can modify it later) whenever you modify the list. Putting it all together, you get this:
struct node* get_sentinel(struct list* plist)
{
// use &plist->head itself as sentinel!
// (works because struct node starts with the next pointer)
return (struct node*) &plist->head;
}
struct list* init_list(){
struct list* plist;
if (!(plist = (struct list*)malloc(sizeof(struct list)))){
return NULL;
}
plist->head = get_sentinel(plist);
return plist;
}
void add_node_at_front(struct node* pnode,struct list* plist){
pnode->next = plist->head;
plist->head = pnode;
}
void add_node_at_back(struct node* pnode,struct list* plist){
struct node *current, *sentinel = get_sentinel(plist);
// search for last element
current = plist->head;
while (current->next != sentinel)
current = current->next;
// insert node
pnode->next = sentinel;
current->next = pnode;
}
void remove_node(struct list* plist, int value){
struct node **prevnext, *sentinel = get_sentinel(plist);
prevnext = &plist->head; // ptr to next pointer of previous node
while (*prevnext != sentinel) {
struct node *current = *prevnext;
if (current->value == value) {
*prevnext = current->next; // remove current from list
free(current); // and free it
break; // we're done!
}
prevnext = &current->next;
}
}
void print_list(struct list* plist){
struct node *current, *sentinel = get_sentinel(plist);
for (current = plist->head; current != sentinel; current = current->next)
print_node(current);
}
A few comments:
I think the remove function doesn't correctly adjust the circular list pointers when you delete the head node and the list is larger than 3 elements. Since the list is circular you have to point the last node in the list to the new head.
You might be able to shorten the remove function slightly by creating a "find_node" function. Since the list is circular, however, there will still be the edge case of deleting the head node which will be more complex than in a non-circular list.
Code "beauty" is in the eye of the beholder. As code goes yours is easy to read and understand which beats a lot of code in the wild.
I use the following to create a dynamic circular singly linked list. All it requires is the size.
Node* createCircularLList(int size)
{
Node *it; // to iterate through the LList
Node *head;
// Create the head /1st Node of the list
head = it = (Node*)malloc(sizeof(Node));
head->id = 1;
// Create the remaining Nodes (from 2 to size)
int i;
for (i = 2; i <= size; ++i) {
it->next = (Node*)malloc(sizeof(Node)); // create next Node
it = it->next; // point to it
it->id = i; // assign its value / id
if (i == 2)
head->next = it; // head Node points to the 2nd Node
}
// close the llist by having the last Node point to the head Node
it->next = head;
return head; // return pointer to start of the list
}
And i define Node ADT like so:
typedef struct Node {
int id;
struct Node *next;
} Node;

Resources