C: Problems with Reversing a linked list - c

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

Related

Inserting a new node into a doubly linked list after a given node

This function inserts a new node after a given node in a doubly linked list.
It works well unless the list is empty or when given node is NULL.
I have tried to solve this problem by inserting the new node as head, but it doesn't add the new node or does problems when adding a second node.
void insert(Polynomial** node, int new_data, int pow) {
Polynomial* new_node = ( Polynomial*)malloc(sizeof( Polynomial));
new_node->num = new_data;
new_node->pow = pow;
if ((*node) == NULL) {
new_node->prev = NULL;
(*node) = new_node;
return;
}
new_node->next = (*node)->next;
(*node)->next = new_node;
new_node->prev = (*node);
if (new_node->next != NULL)
new_node->next->prev = new_node;
}
Struct:
typedef struct Polynomial {
int num;
int pow;
struct Polynomial* next;
struct Polynomial* prev;
}Polynomial;
When you create a new list, the first node's next pointer is unspecified. This could lead to undefined behaviour when inserting the second node, e.g. the 0xcdcdcdcd value you saw. Set it to null before returning:
if ((*node) == NULL) {
new_node->prev = new_node->next = NULL;
(*node) = new_node;
return;
}

Reversing a Linked List using recursion in C

I'm fairly new to C and I am trying to create a function to reverse a linked list, passing only the List itself as a parameter. Is this possible to do without passing a node as a parameter?
Here is my code so far, I know it does not work correctly because I cannot figure out how to make the recursive call on the rest of the list.
void reverse(LL_t *L) {
if (L->head->next == NULL) {
return;
}
node_t *rest = L->head->next;
reverse(rest);
node_t *q = rest->next;
q->next = rest;
rest->next = NULL;
}
As well here are my type definitions.
typedef struct {
node_t *head;
node_t *tail;
} LL_t;
typedef struct _node {
int data;
struct _node *next;
} node_t;
You can reverse the list with a simple loop, recursion is not needed and given your API, not appropriate.
Here is a modified version of your function:
void reverse(LL_t *L) {
node_t *prev = NULL;
node_t *curr = L->head;
L->tail = curr;
while (curr != NULL) {
node_t *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
L->head = prev;
}
If you are required to use recursion, you can test if the list is empty or limited to a singleton and do nothing, otherwise remove the head element, reverse the resulting list and append the element to the end:
void reverse(LL_t *L) {
if (L->head != L->tail) {
/* at least 2 elements */
node_t *node = L->head;
L->head = node->next;
node->next = NULL;
reverse(L);
L->tail = L->tail->next = node;
}
}
Note that this recursive approach may have undefined behavior if the list is too long as reverse will recurse too many times and cause a stack overflow.
struct node {
int value;
struct node* next;
};
Non-recursive definition operating in constant stack space:
void reverse(struct node** ptr) {
struct node* prev_ptr;
struct node* node_ptr;
if (prev_ptr = * ptr) {
node_ptr = prev_ptr -> next;
prev_ptr -> next = NULL;
while (node_ptr) {
struct node* temp = node_ptr -> next;
node_ptr -> next = prev_ptr;
prev_ptr = node_ptr;
node_ptr = temp;
}
* ptr = prev_ptr;
}
}
Extensionally equivalent recursive definition:
void reverse(struct node** ptr) {
struct node* node_ptr;
if (node_ptr = * ptr) {
node_ptr -> next = NULL;
* ptr = reverse_rec(node_ptr, node_ptr -> next);
}
}
struct node* reverse_rec(struct node* prev_ptr, struct node* node_ptr) {
if (! node_ptr) { return prev_ptr; }
struct node* temp = reverse_rec(node_ptr, node_ptr -> next);
node_ptr -> next = prev_ptr;
return temp;
}
This works, but using recursion to reverse a list requires O(n) stack space overhead. The concept here is to advance the static instance of L->head, while keeping a local copy of head for each level of recursion. Recursion continues until the end of the list is reached, then the list is reversed using the local instances of head as reverse() returns backup the call chain.
void reverse(LL_t *L)
{
node_t *head;
if(L->head == NULL || L->head->next == NULL)
return;
head = L->head;
L->head = head->next;
reverse(L);
head->next->next = head; // reverse the nodes
head->next = NULL;
L->tail = head; // ends up setting tail to what was 1st node
}
//A simple program to reverse a Linked List
void reverse(struct node* head_ref)
{
struct node* first;
struct node* rest;
if (head_ref == NULL)
return;
first = head_ref;
rest = first->next;
if (rest == NULL)
return;
reverse(rest);
first->next->next = first;
first->next = NULL;
head_ref = rest;
}

Reversing a Singly Linked List

I know there are multiple questions on the same problem on SO. But somewhere, I am not able to get the logic.
The function that reverses the Linked List is as follows:
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
I am using a global head pointer and the structure of a node in the linked list is:
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
Here, every time the curr node will point to the prev node and at the end when the list is traversed by the curr node, prev node will point to the last node in the list which I make as the head pointer.
But, this logic doesn't reverse the list and only prints the first node. So, I think the code is executed only once but I am not able to catch the mistake.
The other functions to make the program complete:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
void add(int n)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = n;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
temp->next = head;
head = temp;
}
void print()
{
struct node *temp = head;
printf("\n The List is : ");
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp = temp->next;
}
}
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
int main(void)
{
add(1);
add(2);
add(3);
add(4);
add(5);
print();
reverse();
print();
return 0;
}
You are overwriting the curr->next pointer which is then used to iterate the list. Code should be more like this:
void reverse()
{
struct node *curr=head, *prev=NULL;
struct node *next;
while(curr!=NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}

Reversing a linked list and printing the result

I'm writing a function that takes a linked-list reverses the elements in place, then prints the result. I cannot get it to work properly when I run it; it only prints the first value.
typedef struct node {
ElemType val;
struct node *next;
} NODE;
struct list_struct {
NODE *front;
NODE *back;
};
//reverse elements in list
void lst_reverse(LIST *l) {
NODE *p = l->front;
NODE *prev = NULL;
NODE *current = p;
NODE *next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}
p = prev;
lst_print(l);
}
The assignment p = prev does not update the front pointer in your LIST. When you call lst_print(l) you are starting at the old front of the list which is the new back, hence the reason why it will stop after a single iteration.
Instead, you should update the front (and back) of the list with something like:
l->front = prev;
l->back = p;

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