Linked list reverse function leads to infinite printing loop - c

I was writing a C code to reverse a link list. I got into one problem.
If I do not make my next pointer NULL my reverse function works fine, but if I make it null the linked list always keeps printing in the while loop.
Below is the correct program, which works fine.
But if I make *next = NULL, the display function will keep printing in the while loop.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
} *head;
/*************************************************************/
/* */
/* create - Function to create Nodes and add them at last */
/* */
/*************************************************************/
int create(int data)
{
struct node *temp,*ptr = NULL;
//int data = 0;
ptr = head;
//Printf(" Enter the Data for Node : ");
//scanf(" %d ", data);
temp = (struct node *)malloc(sizeof(struct node));
if (ptr == NULL) {
// this is the first node
temp->next = NULL;
temp->data = data;
head = temp;
} else {
// this is not the first node
while (ptr != NULL) {
if (ptr->next == NULL) {
temp->next = NULL;
temp->data = data;
ptr->next = temp;
break;
}
ptr = ptr->next;
}
}
return 0;
}
/*************************************************************/
/* */
/* create_in_front - Function to add Node in Front */
/* */
/*************************************************************/
int create_in_front(int data)
{
struct node *temp,*ptr = NULL;
ptr = head;
temp = (struct node *)malloc(sizeof(struct node));
if (ptr == NULL) {
// this is the first node
temp->next = NULL;
temp->data = data;
head = temp;
} else {
// this is not the first node
temp->next = ptr->next;
temp->data = data;
head = temp;
}
return 0;
}
/*************************************************************/
/* */
/* create_in_between - Function to add Node in between nodes*/
/* */
/*************************************************************/
int create_in_between(int data,int pos)
{
struct node *temp, *ptr = NULL;
int i = 0;
ptr = head;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = data;
for (i = 0; i < pos; i++) {
if (i == pos-1) {
temp->next = ptr->next;
ptr->next = temp;
}
ptr = ptr->next;
}
return 0;
}
/*************************************************************/
/* */
/* delete_in_between - Function to add Node in between nodes*/
/* */
/*************************************************************/
delete_in_between(int pos)
{
struct node *ptr, *prev = NULL;
ptr = head;
int i = 0;
for (i = 0; i < pos; i++) {
if (i == pos-1) {
prev = ptr->next;
free(ptr);
break;
}
prev = ptr;
ptr = ptr->next;
}
return 0;
}
/*************************************************************/
/* */
/* reverse - Function to reverse link list */
/* */
/*************************************************************/
int reverse()
{
struct node *prev = NULL;
struct node *curr = head;
struct node *next = NULL;
curr = head;
while (curr != NULL) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
return 0;
}
/*************************************************************/
/* */
/* display - Function to diplay link list */
/* */
/*************************************************************/
// Function to display Link List
int display()
{
struct node *temp = head;
while (temp != NULL) {
printf("%d->",temp->data);
temp = temp->next;
}
return 0;
}
int main()
{
create(10);
create(20);
create(30);
create(40);
create(50);
create_in_front(34);
create_in_between(55,2);
//delete_in_between(4);
reverse();
display();
return 0;
}
Let me know the logic behind this.

Function create_in_front() is bogus: temp->next = ptr->next; should be changed to temp->next = ptr;
create_in_between() does not handle the case of pos==0.
delete_in_between() is completely dysfunctional: the node is frees but its predecessor still points to it.
reverse() seems correct to me, it could be simplified this way:
int reverse() {
struct node *prev = NULL;
struct node *curr = head;
while (curr != NULL) {
struct node *next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
return 0;
}
The problem seems unrelated to your modifying the reverse() function, maybe a side effect of bugs in the other functions.

Your reverse() function seems correct, but the rest of the code is somewhat overcomplicated. Try something like this:
void create(int data) {
struct node *temp = malloc(sizeof(struct node));
if (temp != NULL) {
temp->next = NULL;
temp->data = data;
if (head == NULL) { // this is the first node
head = temp;
} else {
// this is not the first node
struct node *last = head;
while (last->next)
last = last->next;
last->next = temp;
}
}
}
void create_in_front(int data) {
struct node *temp = malloc(sizeof(struct node));
if (temp != NULL) {
temp->next = head;
temp->data = data;
head = temp;
}
}

Related

Segment Fault - Linked List in C

I am creating a basic linked list in C but I am getting a segment fault when my add to back function is called in my test file. It seems to have a problem because the head of the list is NULL, but I don't see why this is an issue. When I use the cgdb tool, it tells me the error is occurring on the line: prev->next = new_node. I have attached the full code below, please let me know what I am not seeing to fix this.
header file
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
typedef struct Node {
int data;
struct Node *next;
} Node;
Node *create_node(int data);
void free_list(Node *head);
void add_to_front(struct Node **head, int data);
void print_list(struct Node *head);
void reverse_list(struct Node **head);
void add_to_back(Node **head, int data);
#endif // LINKED_LIST_H
.c file
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
/* returns a new node whose data is set to DATA and next is set to NULL */
Node *create_node(int data) {
struct Node *new_node = malloc(sizeof(struct Node));
if (new_node == NULL) {
perror("Malloc failed\n");
}
new_node->data = data;
new_node->next = NULL;
return new_node;
}
/* Frees the list starting at HEAD */
void free_list(Node *head) {
while (head != NULL) {
Node *temp = head->next;
free(head);
head = temp;
}
}
/* Creates a new node whose data is set to DATA and adds it to the front of the
list pointed to by HEAD.
*/
void add_to_front(struct Node **head, int data) {
/* Check if the head is NULL to make sure that we do not dereference a NULL pointer
because that would result in a segfault */
if (head == NULL) return;
struct Node *new_node = create_node(data);
if (*head != NULL) {
/* The list is not empty */
/* The new node's next should point to the head */
new_node->next = *head;
}
/* We must set HEAD using the following line in order to change the original list */
*head = new_node;
/* The following line would not work because it would only change our local copy of HEAD */
/* head = new_node */
}
/* Prints out a linked list starting at HEAD */
void print_list(struct Node *head) {
struct Node *curr;
for (curr = head; curr != NULL; curr = curr->next) {
printf("%d->", curr->data);
}
printf("NULL\n");
}
/* Iteratively reverses a linked list whose first node is HEAD */
void reverse_list(struct Node **head) {
if (head == NULL || *head == NULL) {
return;
}
struct Node *curr = *head;
struct Node *next = (*head)->next;
curr->next = NULL;
while (next != NULL) {
struct Node *temp = next->next;
next->next = curr;
curr = next;
next = temp;
}
*head = curr;
}
/* Creates a new node with a data field set to DATA and adds the node
to the back of the list pointed to by HEAD */
void add_to_back(Node **head, int data) {
if (head == NULL || *head == NULL) {
return;
}
Node *new_node = create_node(data);
Node *prev;
for (Node *curr = *head; curr != NULL; curr = curr->next) {
prev = curr;
}
prev->next = new_node;
}
test file
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"
int main(int argc, char **argv) {
printf("Running tests...\n\n");
Node *head = NULL;
/*********** reverse_list test ***********/
reverse_list(&head);
for (int i = 0; i < 5; ++i) {
add_to_front(&head, i);
reverse_list(&head);
}
int expected_values[] = {3, 1, 0, 2, 4};
Node *curr = head;
for (int i = 0; i < 5; ++i) {
assert(curr->data == expected_values[i]);
curr = curr->next;
}
free_list(head);
printf("Congrats! You have passed the reverse_list test!\n\n");
/************ add_to_back test ***********/
Node *head_2 = NULL;
add_to_back(&head_2, 15);
add_to_back(&head_2, 12);
add_to_back(&head_2, 18);
int expected_values_2[] = {15, 12, 18};
Node *curr_2 = head_2;
for (int i = 0; i < 3; ++i) {
assert(curr_2->data == expected_values_2[i]);
curr_2 = curr_2->next;
}
free_list(head_2);
printf("Congrats! All of the test cases passed!\n");
return 0;
}
The if statement in the function add_to_back
if (head == NULL || *head == NULL) {
return;
}
does not make a sense because it does not allow to append a node to an empty list.
The function can be defined for example like
void add_to_back( Node **head, int data )
{
if ( head == NULL ) return;
Node *new_node = create_node(data);
while ( *head ) head = &( *head )->next;
*head = new_node;
}
Or using your approach then
void add_to_back( Node **head, int data )
{
if ( head == NULL ) return;
Node *new_node = create_node(data);
Node *prev = NULL;
for ( Node *curr = *head; curr != NULL; curr = curr->next )
{
prev = curr;
}
prev == NULL ? ( *head = new_node ) : ( prev->next = new_node );
}
In general this statement
if ( head == NULL ) return;
is also redundant. If the user will pass a null pointer then the function just will have undefined behavior.
On the other hand the function create_node should be written the following way
Node * create_node( int data )
{
struct Node *new_node = malloc(sizeof(struct Node));
if ( new_node != NULL )
{
new_node->data = data;
new_node->next = NULL;
}
return new_node;
}
Correspondingly for example the function add_to_back can be written like
int add_to_back( Node **head, int data )
{
Node *new_node = create_node( data );
int success = new_node != NULL;
if ( success )
{
Node *prev = NULL;
for ( Node *curr = *head; curr != NULL; curr = curr->next )
{
prev = curr;
}
prev == NULL ? ( *head = new_node ) : ( prev->next = new_node );
}
return success;
}
The problem is in the add_to_back() function. Because of first line in that function if (head == NULL || *head == NULL) { return; }, it will keep returning and not executing rest of the code. So, if you print your list after three calls of the add_to_back function, your list has nothing but NULL and that is the reason you are getting a segmentation fault. I did the following change and your code is working fine
`
void add_to_back(Node **head, int data) {
Node *new_node = create_node(data);
if (*head == NULL){
*head = new_node;
return;
}
Node *prev;
for (Node *curr = *head; curr != NULL; curr = curr->next) {
prev = curr;
}
prev->next = new_node;
}
`

What is the problem with this piece of code?

I am writing for deleting the last node of a doubly linked list. But, every time this function is giving me segmentation fault when I have 2 or more than 2 elements in the list.
void deleteEnd()
{
struct node *ptr;
if(head==NULL)
printf("\nList is empty.First add some numbers");
else if(head->next==NULL)
{
head = NULL;
free(head);
}
else
{
ptr = head;
while(ptr->next != NULL)
{
ptr = ptr -> next;
}
ptr -> prev -> next = NULL;
free(ptr);
}
}
Normally, when you are deleting a node from a linked list it is a good practice to pass a reference to the first node of the list as an argument of the function. In your case you are not showing us where the head is coming from, and I think that it could be quite a useful info, and I bet that the error hides there.
That is how the implementation could look like:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// insert end node: this is for testing purposes
struct node *insertEnd(struct node *head, int value) {
struct node *ptr, *new_node;
ptr = head;
new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = value;
new_node->next = NULL;
// The list is empty
if (head == NULL) {
head = new_node;
return head;
}
// Non empty list
while (ptr->next != NULL) {
ptr = ptr->next;
}
ptr->next = new_node;
return head;
}
// delete end node
struct node *deleteEnd(struct node *head) {
struct node *ptr, *preptr;
ptr = head;
preptr = NULL;
// The list is empty
if (head == NULL) {
printf("The list is empty. Nothing to delete.\n");
return head;
}
while(ptr->next != NULL) {
preptr = ptr;
ptr= ptr->next;
}
free(ptr);
if (preptr == NULL) {
head = NULL;
}
else {
preptr->next = NULL;
}
return head;
}
int main(void) {
struct node *llist;
llist = NULL;
llist = insertEnd(llist, 10);
llist = insertEnd(llist, 20);
llist = insertEnd(llist, 30);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
return 0;
}
It is always a great idea to maintain a global variable head and update it after every push/pop. See this:
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
struct node *deleteEnd(struct node *start)
{
struct node *ptr = start;
if(ptr==NULL)
{
printf("\nList is empty!!!");
return start;
}
else if(ptr->next == NULL)
{
free(ptr);
start = NULL;
return start;
}
else
{
while((ptr->next)->next!=NULL) //by doing this you dont have to maintain a prev pointer
{
ptr=ptr->next;
}
struct node *temp = ptr->next;
free(temp);
ptr->next = NULL;
return start;
}
}
Hope this helps!!!

linked list c programming error by inserting new element

I am trying to insert an element but it get the error "Process finished with exit code 11"
struct node {
int key;
struct node *next;
};
struct node* init(){
struct node *head =NULL;
return head;
}
void create(struct node * head,int num) {
struct node * tmp = head;
struct node * prev = NULL;
struct node* new = malloc(sizeof(struct node));
new->key = num;
prev = tmp;
tmp = tmp->next;
while(tmp!= NULL && tmp->key < num){
prev = tmp;
tmp = tmp->next;
}
new->next = tmp;
prev->next = new;
if (tmp== NULL)
head=tmp;
}
int main() {
int num;
struct node* head;
head=init()
printf("Enter data:");
scanf("%d",&num);
create(head,num);
}
i am trying to insert an element into a linked list and the element should be sorted and entered at the same time.can someone tell me that the error is ? i cannot seem to find out the error.
It's not clear what your function create()
void create(struct node * head, int num) {
struct node * tmp = head;
struct node * prev = NULL;
struct node* new = malloc(sizeof(struct node));
new->key = num;
prev = tmp;
tmp = tmp->next;
while (tmp != NULL && tmp->key < num) {
prev = tmp;
tmp = tmp->next;
}
new->next = tmp;
prev->next = new;
if (tmp == NULL)
head = tmp;
}
is supposed to do. You effectively pass it a NULL pointer and return void, so everything it does is meaningless to the outside world.
Thetm starting point for every no bs linked list implementation:
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
typedef struct node_tag {
int value;
struct node_tag *next;
} node_t;
// write functions to encapsulate the data and provide a stable interface:
node_t* node_create_value(int value)
{
node_t *new_node = calloc(1, sizeof *new_node);
if(new_node) new_node->value = value;
return new_node;
}
node_t* node_advance(node_t const *node) { return node->next; }
typedef struct list_tag { // a list usually consists of
node_t *head; // a pointer to the first and
node_t *tail; // a pointer to the last element
// size_t size; // one might want to add that.
} list_t;
list_t list_create(void)
{
list_t list = { NULL, NULL };
return list;
}
// make code based on these functions "speak" for itself:
node_t* list_begin(list_t const *list) { return list->head; }
node_t* list_end (list_t const *list) { return list->tail; }
bool list_is_empty(list_t const *list) { return !list_begin(list); }
// common operations for lists:
node_t* list_push_front(list_t *list, int value)
{
node_t *new_node = node_create_value(value);
if (!new_node)
return NULL;
new_node->next = list->head;
return list->head = new_node;
}
node_t* list_push_back(list_t *list, int value)
{
// push_back on an empty list is push_front:
if (list_is_empty(list))
return list->tail = list_push_front(list, value);
node_t *new_node = node_create_value(value);
if (!new_node)
return NULL;
list->tail->next = new_node;
return list->tail = new_node;
}
node_t* list_insert_after(list_t *list, node_t *node, int value)
{
if (list_end(list) == node)
return list_push_back(list, value);
node_t *new_node = node_create_value(value);
if (!new_node)
return NULL;
new_node->next = node->next;
return node->next = new_node;
}
node_t* list_insert_sorted(list_t *list, int value)
{
// first handle the special cases that don't require iterating the whole list:
if (list_is_empty(list) || value < list_begin(list)->value)
return list_push_front(list, value);
if (value > list_end(list)->value)
return list_push_back(list, value);
// the general (worst) case:
for (node_t *current_node = list_begin(list); node_advance(current_node); current_node = node_advance(current_node))
if (value < node_advance(current_node)->value)
return list_insert_after(list, current_node, value);
return NULL; // should never happen
}
void list_print(list_t const *list)
{
for (node_t *current_node = list_begin(list); current_node; current_node = node_advance(current_node))
printf("%d\n", current_node->value);
}
void list_free(list_t *list)
{
for(node_t *current_node = list_begin(list), *next_node; current_node; current_node = next_node) {
next_node = current_node->next;
free(current_node);
}
}
// user code should not be required to know anything about the inner workings
// of our list:
int main(void)
{
list_t list = list_create();
for (int i = 1; i < 10; i += 2) {
if (!list_push_back(&list, i)) {
list_free(&list);
fputs("Not enough memory :(\n\n", stderr);
return EXIT_FAILURE;
}
}
list_print(&list);
putchar('\n');
for (int i = 0; i < 11; i += 2) {
if (!list_insert_sorted(&list, i)) {
list_free(&list);
fputs("Not enough memory :(\n\n", stderr);
return EXIT_FAILURE;
}
}
list_print(&list);
list_free(&list);
}
Output:
1
3
5
7
9
0
1
2
3
4
5
6
7
8
9
10

Linked List output not showing correctly

I can't figure out where is the problem in my code:
typedef struct list List;
struct list {
int data;
List* next;
};
void insert_sorted(List** head, int value);
int main() {
List* head = NULL;
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
insert_sorted(&head, 3);
insert_sorted(&head, 2);
insert_sorted(&head, 40);
insert_sorted(&head, 10);
//insert_sorted(&head, 40);
List* temp = head;
while (temp != NULL) {
printf("%d\t", temp->data);
temp = temp->next;
}
printf("\n\n");
return 0;
}
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) {
node->next = *head;
*head = node;
} else {
temp = *head;
while (temp->next != NULL) {
if (temp->data < value && (temp->next)->data > value) {
node->next = temp->next;
temp->next = node;
} else
temp = temp->next;
}
temp->next = node;
}
}
1:
Run the code and see results. (Running and running...) after sorting data it is repeating some values forever.
2:
Go to
//insert_sorted(&head, 40);
this line an remove comment symbols.
Run the code and mark the result.(Time limit exceeded)
3:
Find this and remove comments:
/*
insert_sorted(&head, 20);
insert_sorted(&head, 10);
insert_sorted(&head, 5);
*/
Run and see results; (Again some problems)
Finally:
Remove all comments symbols and run it, this time it is working without any error but not as expected (List is not sorted correctly);
But why this is happening? Any help will be appreciated, and I am not at home at this but a learner.
Your void insert_sorted(List** head, int value) function is doing too much work.
void insert_sorted(List** head, int value) {
List* node = malloc(sizeof *node);
node->data = value;
for( ; *head ; head = &(*head)->next) {
if ((*head)->data > value) break; // we should insert before *head
}
// When we get here *head points to the pointer that needs to get node's value
// This can either be the original head (as supplied as argument tothe function)
// or some of the -> next pointers, or even the last ->next pointer.
node->next = *head;
*head = node;
}
The problem can be fixed as follows. If the node is inserted in the middle, the function can return and does not need to append the value at the end.
void insert_sorted(List** head, int value) {
List* temp = NULL;
List* node = (List*)malloc(sizeof(List));
node->data = value;
node->next = NULL;
if (*head == NULL || (*head)->data >= value) { // <-- fix
node->next = *head;
*head = node;
}
else {
temp = *head;
while (temp->next != NULL) {
if ( (temp->next)->data > value ) {
node->next = temp->next;
temp->next = node;
return; // <-- fix
}
else
temp = temp->next;
}
temp->next = node;
}
}
Your code sometimes inserted value twice (when value was not placed at the end of the list). This should fix the problem:
while(temp->next != NULL)
{
if(temp->data < value && (temp->next)->data > value)
{
node->next = temp->next;
temp->next = node;
break;
}
else
temp = temp->next;
}
if(temp->next == NULL)
temp->next = node;

reverse a link list [duplicate]

I wonder if there exists some logic to reverse a singly-linked list using only two pointers.
The following is used to reverse the single linked list using three pointers namely p, q, r:
struct node {
int data;
struct node *link;
};
void reverse() {
struct node *p = first,
*q = NULL,
*r;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
first = q;
}
Is there any other alternate to reverse the linked list? What would be the best logic to reverse a singly linked list, in terms of time complexity?
Any alternative? No, this is as simple as it gets, and there's no fundamentally-different way of doing it. This algorithm is already O(n) time, and you can't get any faster than that, as you must modify every node.
It looks like your code is on the right track, but it's not quite working in the form above. Here's a working version:
#include <stdio.h>
typedef struct Node {
char data;
struct Node* next;
} Node;
void print_list(Node* root) {
while (root) {
printf("%c ", root->data);
root = root->next;
}
printf("\n");
}
Node* reverse(Node* root) {
Node* new_root = 0;
while (root) {
Node* next = root->next;
root->next = new_root;
new_root = root;
root = next;
}
return new_root;
}
int main() {
Node d = { 'd', 0 };
Node c = { 'c', &d };
Node b = { 'b', &c };
Node a = { 'a', &b };
Node* root = &a;
print_list(root);
root = reverse(root);
print_list(root);
return 0;
}
I hate to be the bearer of bad news but I don't think your three-pointer solution actually works. When I used it in the following test harness, the list was reduced to one node, as per the following output:
==========
4
3
2
1
0
==========
4
==========
You won't get better time complexity than your solution since it's O(n) and you have to visit every node to change the pointers, but you can do a solution with only two extra pointers quite easily, as shown in the following code:
#include <stdio.h>
// The list element type and head.
struct node {
int data;
struct node *link;
};
static struct node *first = NULL;
// A reverse function which uses only two extra pointers.
void reverse() {
// curNode traverses the list, first is reset to empty list.
struct node *curNode = first;
first = NULL;
// Until no more in list, insert current before first and advance.
while (curNode != NULL) {
// Need to save next node since we're changing the current.
struct node *nxtNode = curNode->link;
// Insert at start of new list.
curNode->link = first;
first = curNode;
// Advance to next.
curNode = nxtNode;
}
}
// Code to dump the current list.
static void dumpNodes() {
struct node *curNode = first;
printf ("==========\n");
while (curNode != NULL) {
printf ("%d\n", curNode->data);
curNode = curNode->link;
}
}
// Test harness main program.
int main (void) {
int i;
struct node *newnode;
// Create list (using actually the same insert-before-first
// that is used in reverse function.
for (i = 0; i < 5; i++) {
newnode = malloc (sizeof (struct node));
newnode->data = i;
newnode->link = first;
first = newnode;
}
// Dump list, reverse it, then dump again.
dumpNodes();
reverse();
dumpNodes();
printf ("==========\n");
return 0;
}
This code outputs:
==========
4
3
2
1
0
==========
0
1
2
3
4
==========
which I think is what you were after. It can actually do this since, once you've loaded up first into the pointer traversing the list, you can re-use first at will.
#include <stddef.h>
typedef struct Node {
struct Node *next;
int data;
} Node;
Node * reverse(Node *cur) {
Node *prev = NULL;
while (cur) {
Node *temp = cur;
cur = cur->next; // advance cur
temp->next = prev;
prev = temp; // advance prev
}
return prev;
}
Here's the code to reverse a singly linked list in C.
And here it is pasted below:
// reverse.c
#include <stdio.h>
#include <assert.h>
typedef struct node Node;
struct node {
int data;
Node *next;
};
void spec_reverse();
Node *reverse(Node *head);
int main()
{
spec_reverse();
return 0;
}
void print(Node *head) {
while (head) {
printf("[%d]->", head->data);
head = head->next;
}
printf("NULL\n");
}
void spec_reverse() {
// Create a linked list.
// [0]->[1]->[2]->NULL
Node node2 = {2, NULL};
Node node1 = {1, &node2};
Node node0 = {0, &node1};
Node *head = &node0;
print(head);
head = reverse(head);
print(head);
assert(head == &node2);
assert(head->next == &node1);
assert(head->next->next == &node0);
printf("Passed!");
}
// Step 1:
//
// prev head next
// | | |
// v v v
// NULL [0]->[1]->[2]->NULL
//
// Step 2:
//
// prev head next
// | | |
// v v v
// NULL<-[0] [1]->[2]->NULL
//
Node *reverse(Node *head)
{
Node *prev = NULL;
Node *next;
while (head) {
next = head->next;
head->next = prev;
prev = head;
head = next;
}
return prev;
}
Robert Sedgewick, "Algorithms in C", Addison-Wesley, 3rd Edition, 1997, [Section 3.4]
In case that is not a cyclic list ,hence NULL is the last link.
typedef struct node* link;
struct node{
int item;
link next;
};
/* you send the existing list to reverse() and returns the reversed one */
link reverse(link x){
link t, y = x, r = NULL;
while(y != NULL){
t = y->next;
y-> next = r;
r = y;
y = t;
}
return r;
}
Yes. I'm sure you can do this the same way you can swap two numbers without using a third. Simply cast the pointers to a int/long and perform the XOR operation a couple of times. This is one of those C tricks that makes for a fun question, but doesn't have any practical value.
Can you reduce the O(n) complexity? No, not really. Just use a doubly linked list if you think you are going to need the reverse order.
Just for fun (although tail recursion optimization should stop it eating all the stack):
Node* reverse (Node *root, Node *end) {
Node *next = root->next;
root->next = end;
return (next ? reverse(next, root) : root);
}
root = reverse(root, NULL);
You need a track pointer which will track the list.
You need two pointers :
first pointer to pick first node.
second pointer to pick second node.
Processing :
Move Track Pointer
Point second node to first node
Move First pointer one step, by assigning second pointer to one
Move Second pointer one step, By assigning Track pointer to second
Node* reverselist( )
{
Node *first = NULL; // To keep first node
Node *second = head; // To keep second node
Node *track = head; // Track the list
while(track!=NULL)
{
track = track->next; // track point to next node;
second->next = first; // second node point to first
first = second; // move first node to next
second = track; // move second node to next
}
track = first;
return track;
}
How about the more readable:
Node *pop (Node **root)
{
Node *popped = *root;
if (*root) {
*root = (*root)->next;
}
return (popped);
}
void push (Node **root, Node *new_node)
{
new_node->next = *root;
*root = new_node;
}
Node *reverse (Node *root)
{
Node *new_root = NULL;
Node *next;
while ((next = pop(&root))) {
push (&new_root, next);
}
return (new_root);
}
To swap two variables without the use of a temporary variable,
a = a xor b
b = a xor b
a = a xor b
fastest way is to write it in one line
a = a ^ b ^ (b=a)
Similarly,
using two swaps
swap(a,b)
swap(b,c)
solution using xor
a = a^b^c
b = a^b^c
c = a^b^c
a = a^b^c
solution in one line
c = a ^ b ^ c ^ (a=b) ^ (b=c)
b = a ^ b ^ c ^ (c=a) ^ (a=b)
a = a ^ b ^ c ^ (b=c) ^ (c=a)
The same logic is used to reverse a linked list.
typedef struct List
{
int info;
struct List *next;
}List;
List* reverseList(List *head)
{
p=head;
q=p->next;
p->next=NULL;
while(q)
{
q = (List*) ((int)p ^ (int)q ^ (int)q->next ^ (int)(q->next=p) ^ (int)(p=q));
}
head = p;
return head;
}
Here's a simpler version in Java. It does use only two pointers curr & prev
public void reverse(Node head) {
Node curr = head, prev = null;
while (head.next != null) {
head = head.next; // move the head to next node
curr.next = prev; //break the link to the next node and assign it to previous
prev = curr; // we are done with previous, move it to next node
curr = head; // current moves along with head
}
head.next = prev; //for last node
}
Work out the time complexity of the algorithm you are using now and it should be obvious that it can not be improved.
I don't understand why there is need to return head as we are passing it as argument. We are passing head of the link list then we can update also. Below is simple solution.
#include<stdio.h>
#include<conio.h>
struct NODE
{
struct NODE *next;
int value;
};
typedef struct NODE node;
void reverse(node **head);
void add_end(node **head,int val);
void alloc(node **p);
void print_all(node *head);
void main()
{
node *head;
clrscr();
head = NULL;
add_end( &head, 1 );
add_end( &head, 2 );
add_end( &head, 3 );
print_all( head );
reverse( &head );
print_all( head );
getch();
}
void alloc(node **p)
{
node *temp;
temp = (node *) malloc( sizeof(node *) );
temp->next = NULL;
*p = temp;
}
void add_end(node **head,int val)
{
node *temp,*new_node;
alloc(&new_node);
new_node->value = val;
if( *head == NULL )
{
*head = new_node;
return;
}
for(temp = *head;temp->next!=NULL;temp=temp->next);
temp->next = new_node;
}
void print_all(node *head)
{
node *temp;
int index=0;
printf ("\n\n");
if (head == NULL)
{
printf (" List is Empty \n");
return;
}
for (temp=head; temp != NULL; temp=temp->next,index++)
printf (" %d ==> %d \n",index,temp->value);
}
void reverse(node **head)
{
node *next,*new_head;
new_head=NULL;
while(*head != NULL)
{
next = (*head)->next;
(*head)->next = new_head;
new_head = (*head);
(*head) = next;
}
(*head)=new_head;
}
#include <stdio.h>
#include <malloc.h>
tydef struct node
{
int info;
struct node *link;
} *start;
void main()
{
rev();
}
void rev()
{
struct node *p = start, *q = NULL, *r;
while (p != NULL)
{
r = q;
q = p;
p = p->link;
q->link = r;
}
start = q;
}
curr = head;
prev = NULL;
while (curr != NULL) {
next = curr->next; // store current's next, since it will be overwritten
curr->next = prev;
prev = curr;
curr = next;
}
head = prev; // update head
No, nothing faster than the current O(n) can be done. You need to alter every node, so time will be proportional to the number of elements anyway and that's O(n) you already have.
Using two pointers while maintaining time complexity of O(n), the fastest achievable, might only be possible through number casting of pointers and swapping their values. Here is an implementation:
#include <stdio.h>
typedef struct node
{
int num;
struct node* next;
}node;
void reverse(node* head)
{
node* ptr;
if(!head || !head->next || !head->next->next) return;
ptr = head->next->next;
head->next->next = NULL;
while(ptr)
{
/* Swap head->next and ptr. */
head->next = (unsigned)(ptr =\
(unsigned)ptr ^ (unsigned)(head->next =\
(unsigned)head->next ^ (unsigned)ptr)) ^ (unsigned)head->next;
/* Swap head->next->next and ptr. */
head->next->next = (unsigned)(ptr =\
(unsigned)ptr ^ (unsigned)(head->next->next =\
(unsigned)head->next->next ^ (unsigned)ptr)) ^ (unsigned)head->next->next;
}
}
void add_end(node* ptr, int n)
{
while(ptr->next) ptr = ptr->next;
ptr->next = malloc(sizeof(node));
ptr->next->num = n;
ptr->next->next = NULL;
}
void print(node* ptr)
{
while(ptr = ptr->next) printf("%d ", ptr->num);
putchar('\n');
}
void erase(node* ptr)
{
node *end;
while(ptr->next)
{
if(ptr->next->next) ptr = ptr->next;
else
{
end = ptr->next;
ptr->next = NULL;
free(end);
}
}
}
void main()
{
int i, n = 5;
node* dummy_head;
dummy_head->next = NULL;
for(i = 1; i <= n ; ++i) add_end(dummy_head, i);
print(dummy_head);
reverse(dummy_head);
print(dummy_head);
erase(dummy_head);
}
I have a slightly different approach. I wanted to make use of the existing functions (like insert_at(index), delete_from(index)) to reverse the list (something like a right shift operation). The complexity is still O(n) but the advantage is more reused code. Have a look at another_reverse() method and let me know what you all think.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* next;
};
struct node* head = NULL;
void printList(char* msg) {
struct node* current = head;
printf("\n%s\n", msg);
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
}
void insert_beginning(int data) {
struct node* newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
} else {
newNode->next = head;
head = newNode;
}
}
void insert_at(int data, int location) {
struct node* newNode = (struct node*) malloc(sizeof(struct node));
newNode->data = data;
newNode->next = NULL;
if (head == NULL)
{
head = newNode;
}
else {
struct node* currentNode = head;
int index = 0;
while (currentNode != NULL && index < (location - 1)) {
currentNode = currentNode->next;
index++;
}
if (currentNode != NULL)
{
if (location == 0) {
newNode->next = currentNode;
head = newNode;
} else {
newNode->next = currentNode->next;
currentNode->next = newNode;
}
}
}
}
int delete_from(int location) {
int retValue = -1;
if (location < 0 || head == NULL)
{
printf("\nList is empty or invalid index");
return -1;
} else {
struct node* currentNode = head;
int index = 0;
while (currentNode != NULL && index < (location - 1)) {
currentNode = currentNode->next;
index++;
}
if (currentNode != NULL)
{
// we've reached the node just one prior to the one we want to delete
if (location == 0) {
if (currentNode->next == NULL)
{
// this is the only node in the list
retValue = currentNode->data;
free(currentNode);
head = NULL;
} else {
// the next node should take its place
struct node* nextNode = currentNode->next;
head = nextNode;
retValue = currentNode->data;
free(currentNode);
}
} // if (location == 0)
else {
// the next node should take its place
struct node* nextNode = currentNode->next;
currentNode->next = nextNode->next;
if (nextNode != NULL
) {
retValue = nextNode->data;
free(nextNode);
}
}
} else {
printf("\nInvalid index");
return -1;
}
}
return retValue;
}
void another_reverse() {
if (head == NULL)
{
printf("\nList is empty\n");
return;
} else {
// get the tail pointer
struct node* tailNode = head;
int index = 0, counter = 0;
while (tailNode->next != NULL) {
tailNode = tailNode->next;
index++;
}
// now tailNode points to the last node
while (counter != index) {
int data = delete_from(index);
insert_at(data, counter);
counter++;
}
}
}
int main(int argc, char** argv) {
insert_beginning(4);
insert_beginning(3);
insert_beginning(2);
insert_beginning(1);
insert_beginning(0);
/* insert_at(5, 0);
insert_at(4, 1);
insert_at(3, 2);
insert_at(1, 1);*/
printList("Original List\0");
//reverse_list();
another_reverse();
printList("Reversed List\0");
/* delete_from(2);
delete_from(2);*/
//printList();
return 0;
}
using 2-pointers....bit large but simple and efficient
void reverse()
{
int n=0;
node *temp,*temp1;
temp=strptr;
while(temp->next!=NULL)
{
n++; //counting no. of nodes
temp=temp->next;
}
// we will exchange ist by last.....2nd by 2nd last so.on....
int i=n/2;
temp=strptr;
for(int j=1;j<=(n-i+1);j++)
temp=temp->next;
// i started exchanging from in between ....so we do no have to traverse list so far //again and again for exchanging
while(i>0)
{
temp1=strptr;
for(int j=1;j<=i;j++)//this loop for traversing nodes before n/2
temp1=temp1->next;
int t;
t=temp1->info;
temp1->info=temp->info;
temp->info=t;
i--;
temp=temp->next;
//at the end after exchanging say 2 and 4 in a 5 node list....temp will be at 5 and we will traverse temp1 to ist node and exchange ....
}
}
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *link;
};
struct node *first=NULL,*last=NULL,*next,*pre,*cur,*temp;
void create()
{
cur=(struct node*) malloc(sizeof(struct node));
printf("enter first data to insert");
scanf("%d",&cur->data);
first=last=cur;
first->link=NULL;
}
void insert()
{
int pos,c;
cur=(struct node*) malloc(sizeof(struct node));
printf("enter data to insert and also its position");
scanf("%d%d",&cur->data,&pos);
if(pos==1)
{
cur->link=first;
first=cur;
}
else
{
c=1;
next=first;
while(c<pos)
{
pre=next;
next=next->link;
c++;
}
if(pre==NULL)
{
printf("Invalid position");
}
else
{
cur->link=pre->link;
pre->link=cur;
}
}
}
void display()
{
cur=first;
while(cur!=NULL)
{
printf("data= %d\t address= %u\n",cur->data,cur);
cur=cur->link;
}
printf("\n");
}
void rev()
{
pre=NULL;
cur=first;
while(cur!=NULL)
{
next=cur->link;
cur->link=pre;
pre=cur;
cur=next;
}
first=pre;
}
void main()
{
int choice;
clrscr();
do
{
printf("Options are: -\n1:Create\n2:Insert\n3:Display\n4:Reverse\n0:Exit\n");
printf("Enter your choice: - ");
scanf("%d",&choice);
switch(choice)
{
case 1:
create();
break;
case 2:
insert();
break;
case 3:
display();
break;
case 4:
rev();
break;
case 0:
exit(0);
default:
printf("wrong choice");
}
}
while(1);
}
Yes there is a way using only two pointers. That is by creating new linked list where the first node is the first node of the given list and second node of the first list is added at the start of the new list and so on.
Here is my version:
void reverse(ListElem *&head)
{
ListElem* temp;
ListElem* elem = head->next();
ListElem* prev = head;
head->next(0);
while(temp = elem->next())
{
elem->next(prev);
prev = elem;
elem = temp;
}
elem->next(prev);
head = elem;
}
where
class ListElem{
public:
ListElem(int val): _val(val){}
ListElem *next() const { return _next; }
void next(ListElem *elem) { _next = elem; }
void val(int val){ _val = val; }
int val() const { return _val;}
private:
ListElem *_next;
int _val;
};
I am using java to implement this and approach is test driven development hence test cases are also attached.
The Node class that represent single node -
package com.adnan.linkedlist;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 12:02 PM
*/
public class Node {
public Node(int value, Node node){
this.value = value;
this.node = node;
}
private int value;
private Node node;
public int getValue() {
return value;
}
public Node getNode() {
return node;
}
public void setNode(Node node){
this.node = node;
}
}
Service class that takes start node as input and reserve it without using extra space.
package com.adnan.linkedlist;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 11:54 AM
*/
public class SinglyLinkedListReversal {
private static final SinglyLinkedListReversal service
= new SinglyLinkedListReversal();
public static SinglyLinkedListReversal getService(){
return service;
}
public Node reverse(Node start){
if (hasOnlyNodeInLinkedList(start)){
return start;
}
Node firstNode, secondNode, thirdNode;
firstNode = start;
secondNode = firstNode.getNode();
while (secondNode != null ){
thirdNode = secondNode.getNode();
secondNode.setNode(firstNode);
firstNode = secondNode;
secondNode = thirdNode;
}
start.setNode(null);
return firstNode;
}
private boolean hasOnlyNodeInLinkedList(Node start) {
return start.getNode() == null;
}
}
And The test case that covers above scenario. Please note that you require junit jars. I am using testng.jar; you can use any whatever pleases you..
package com.adnan.linkedlist;
import org.testng.annotations.Test;
import static org.testng.AssertJUnit.assertTrue;
/**
* User : Adnan
* Email : sendtoadnan#gmail.com
* Date : 9/21/13
* Time : 12:11 PM
*/
public class SinglyLinkedListReversalTest {
private SinglyLinkedListReversal reversalService =
SinglyLinkedListReversal.getService();
#Test
public void test_reverseSingleElement() throws Exception {
Node node = new Node(1, null);
reversalService.reverse(node);
assertTrue(node.getNode() == null);
assertTrue(node.getValue() == 1);
}
//original - Node1(1) -> Node2(2) -> Node3(3)
//reverse - Node3(3) -> Node2(2) -> Node1(1)
#Test
public void test_reverseThreeElement() throws Exception {
Node node3 = new Node(3, null);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 3; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverseFourElement() throws Exception {
Node node4 = new Node(4, null);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 4; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverse10Element() throws Exception {
Node node10 = new Node(10, null);
Node node9 = new Node(9, node10);
Node node8 = new Node(8, node9);
Node node7 = new Node(7, node8);
Node node6 = new Node(6, node7);
Node node5 = new Node(5, node6);
Node node4 = new Node(4, node5);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 10; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
#Test
public void test_reverseTwoElement() throws Exception {
Node node2 = new Node(2, null);
Node start = new Node(1, node2);
start = reversalService.reverse(start);
Node test = start;
for (int i = 2; i >=1 ; i -- ){
assertTrue(test.getValue() == i);
test = test.getNode();
}
}
}
A simple algorithm if you use the linked list as a stack structure:
#include <stdio.h>
#include <stdlib.h>
typedef struct list {
int key;
char value;
struct list* next;
} list;
void print(list*);
void add(list**, int, char);
void reverse(list**);
void deleteList(list*);
int main(void) {
list* head = NULL;
int i=0;
while ( i++ < 26 ) add(&head, i, i+'a');
printf("Before reverse: \n");
print(head);
printf("After reverse: \n");
reverse(&head);
print(head);
deleteList(head);
}
void deleteList(list* l) {
list* t = l;
while ( t != NULL ) {
list* tmp = t;
t = t->next;
free(tmp);
}
}
void print(list* l) {
list* t = l;
while ( t != NULL) {
printf("%d:%c\n", t->key, t->value);
t = t->next;
}
}
void reverse(list** head) {
list* tmp = *head;
list* reversed = NULL;
while ( tmp != NULL ) {
add(&reversed, tmp->key, tmp->value);
tmp = tmp->next;
}
deleteList(*head);
*head = reversed;
}
void add(list** head, int k, char v) {
list* t = calloc(1, sizeof(list));
t->key = k; t->value = v;
t->next = *head;
*head = t;
}
The performance may be affected since additional function call to the add and malloc so the algorithms of address swaps are better but that one actually creates new list so you can use additional options like sort or remove items if you add a callback function as parameter to the reverse.
Here is a slightly different, but simple approach in C++11:
#include <iostream>
struct Node{
Node(): next(NULL){}
Node *next;
std::string data;
};
void printlist(Node* l){
while(l){
std::cout<<l->data<<std::endl;
l = l->next;
}
std::cout<<"----"<<std::endl;
}
void reverse(Node*& l)
{
Node* prev = NULL;
while(l){
auto next = l->next;
l->next = prev;
prev=l;
l=next;
}
l = prev;
}
int main() {
Node s,t,u,v;
s.data = "1";
t.data = "2";
u.data = "3";
v.data = "4";
s.next = &t;
t.next = &u;
u.next = &v;
Node* ptr = &s;
printlist(ptr);
reverse(ptr);
printlist(ptr);
return 0;
}
Output here
Following is one implementation using 2 pointers (head and r)
ListNode * reverse(ListNode* head) {
ListNode *r = NULL;
if(head) {
r = head->next;
head->next = NULL;
}
while(r) {
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));
r->next = reinterpret_cast<ListNode*>(size_t(r->next) ^ size_t(head));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r->next));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
r = reinterpret_cast<ListNode*>(size_t(r) ^ size_t(head));
head = reinterpret_cast<ListNode*>(size_t(head) ^ size_t(r));
}
return head;
}
here is a little simple solution...
void reverse()
{
node * pointer1 = head->next;
if(pointer1 != NULL)
{
node *pointer2 = pointer1->next;
pointer1->next = head;
head->next = NULL;
head = pointer1;
if(pointer2 != NULL)
{
while(pointer2 != NULL)
{
pointer1 = pointer2;
pointer2 = pointer2->next;
pointer1->next = head;
head = pointer1;
}
pointer1->next = head;
head = pointer1;
}
}
}
You can have solution of this problem with help of only one extra pointer, that has to be static for the reverse function. It's in O(n) complexity.
#include<stdio.h>
#include<stdlib.h>
typedef struct List* List;
struct List {
int val;
List next;
};
List reverse(List list) { /* with recursion and one static variable*/
static List tail;
if(!list || !list->next) {
tail = list;
return tail;
} else {
reverse1(list->next);
list->next->next = list;
list->next = NULL;
return tail;
}
}
As an alternative, you can use recursion-
struct node* reverseList(struct node *head)
{
if(head == NULL) return NULL;
if(head->next == NULL) return head;
struct node* second = head->next;
head->next = NULL;
struct node* remaining = reverseList(second);
second->next = head;
return remaining;
}
class Node {
Node next;
int data;
Node(int item) {
data = item;
next = null;
}
}
public class LinkedList {
static Node head;
//Print LinkedList
public static void printList(Node node){
while(node!=null){
System.out.print(node.data+" ");
node = node.next;
}
System.out.println();
}
//Reverse the LinkedList Utility
public static Node reverse(Node node){
Node new_node = null;
while(node!=null){
Node next = node.next;
node.next = new_node;
new_node = node;
node = next;
}
return new_node;
}
public static void main(String[] args) {
//Creating LinkedList
LinkedList.head = new Node(1);
LinkedList.head.next = new Node(2);
LinkedList.head.next.next = new Node(3);
LinkedList.head.next.next.next = new Node(4);
LinkedList.printList(LinkedList.head);
Node node = LinkedList.reverse(LinkedList.head);
LinkedList.printList(node);
}
}

Resources