114

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?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Madhan
  • 2,609
  • 7
  • 26
  • 22

36 Answers36

135

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'm not sure about 'obvious errors' in the original. Design-wise, not passing the head of the list in and not returning the new head is a bad idea. The only bug, though, is the last line in the `reverse()` function should be setting first, I believe. Otherwise, the original code worked OK when plugged into your neat test harness. You get +1 from me even so - but an explanation of what you consider the 'obvious errors' would improve your answer. – Jonathan Leffler Nov 26 '09 at 05:50
  • Yes, `q = first` was biggest error I had in mind, though I consider the confusion over where the input is coming from and how reverse returns a value to be two more; I suppose it was my fault for not looking at it any further than that. –  Nov 26 '09 at 06:06
  • 2
    Isn't there a bug in the above code? Inside the while loop, you are creating a new 'next' pointer each time. So if there are N nodes in the linked list, you are creating N new pointers and you are not freeing or deleting them. I think it would be correct if you create the 'next' pointer before the while loop and just make the assignment 'next = root->next' inside the while loop. – aks Feb 17 '10 at 15:56
  • 8
    @aks: There is no leak. Notice malloc/etc. are not called so there isn't any need to free. The variable 'next' is scoped to the loop, but that's perfectly okay. –  Feb 18 '10 at 01:06
  • 1
    Even if there is no leak, What is the need of declaring next every time, as aks mentioned, "it would be correct if you create the 'next' pointer before the while loop and just make the assignment 'next = root->next' inside the while loop.", Isn't it? – Jagdish Jun 20 '15 at 18:46
  • 1
    I like your linked list literals, that is neat. –  Nov 30 '15 at 02:03
  • 1
    @Jagdish — there is no cost to declaring the variable in the loop and limiting the scope of variables is a good idea. Look at the optimized assembler output for a version with the variable defined in the loop and one with the variable defined outside the loop. – Jonathan Leffler Apr 14 '22 at 15:51
44

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.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    Very elegant. Reusing the `first` pointer on the linked list itself allows the solution to use only 2 *extra* pointers, but 3 *total* pointers are still necessary for this. – Kevin Kibler Feb 26 '10 at 21:23
  • You are using first, curNode and nxtNode, total of three pointers for this. how come this is a two pointer solution? – Yash Oct 30 '14 at 06:46
  • @Yash, read again, two _extra_ pointers on top of `first`. The same way the OP's three-pointer solution had `first`, `p`, `q` and `r`. – paxdiablo Oct 30 '14 at 13:03
  • @paxdiablo oh! my bad. Sorry, I misunderstood the question. Thanks :) – Yash Oct 30 '14 at 14:58
25
#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;
}
splicer
  • 5,344
  • 4
  • 42
  • 47
13

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;
}
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
4

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

limitcracker
  • 2,208
  • 3
  • 24
  • 23
3

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.

Community
  • 1
  • 1
brianegge
  • 29,240
  • 13
  • 74
  • 99
  • …and a new 64-bit compatibility issue is born, if you're not careful. You're unlikely to buy any performance this way either. – Left For Archive Nov 26 '09 at 05:26
  • 2
    This will not affect the time complexity - that is, it won't make the solution any *better* than linear time. I mean, you might save 4 or 8 bytes of memory, but that won't change the overall complexity of the algorithm. – poundifdef Nov 26 '09 at 05:28
  • @rascher, time complexity was the *second* part of the question. The first part had to do with reducing the number of pointers required. – paxdiablo Nov 26 '09 at 05:56
  • 2
    I think the original poster was looking for a cheap C trick. In my experience - and I have profiled it :) - the typical avoiding intermediary tricks are actually slower than just using an intermediary. – Will Nov 26 '09 at 06:24
  • The link is broken, but I'm sure swapping 2 numbers using XOR is old-school :) – Dane Nov 13 '17 at 14:40
  • you can do it in constant time, bruh. – user1095108 Oct 23 '21 at 04:11
3

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);
Andrew Johnson
  • 7,277
  • 4
  • 23
  • 27
  • 2
    I think "should" is overstating the case a bit. Your C compiler "might" do a tail-call optimization, and it's easy enough to check for a given compiler/options whether it does or not: look at the disassembly. Or give it a few million nodes and see if it crashes ;-) – Steve Jessop Nov 26 '09 at 13:11
3

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;

}

Sumit Arora
  • 5,051
  • 7
  • 37
  • 57
2

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;
}  
sr01853
  • 6,043
  • 1
  • 19
  • 39
  • 2
    This assumes an int is the same size as a pointer, it wont work on amd64 systems (you could use `intptr_t`). While interesting - swapping this way is sub-optimal on modern systems. – ideasman42 Aug 07 '14 at 00:48
  • The one-line versions run into sequencing problems due to a lack of sequence points. The results are unreliable at best. These methods for swapping are not great. They are party tricks rather than real code. – Jonathan Leffler Apr 14 '22 at 15:59
2

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);
}
Andrew Johnson
  • 7,277
  • 4
  • 23
  • 27
2

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
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
ernesto
  • 1,899
  • 4
  • 26
  • 39
  • The question is looking for a C solution, not one in Java – Degustaf Mar 18 '15 at 20:02
  • 1
    The question is more about doing the reverse operation with only two additional pointers (or references). Whether its C or Java the logic is same. – ernesto Mar 18 '15 at 21:05
1
#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;
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
1

Work out the time complexity of the algorithm you are using now and it should be obvious that it can not be improved.

John La Rooy
  • 295,403
  • 53
  • 369
  • 502
1

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;
}
1
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
Jostein Topland
  • 990
  • 8
  • 16
0
#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);
}
Dirty-flow
  • 2,306
  • 11
  • 30
  • 49
0

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;
        }       
   }
 }
gevorg
  • 4,835
  • 4
  • 35
  • 52
0

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.

taskinoor
  • 45,586
  • 12
  • 116
  • 142
0

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.

sharptooth
  • 167,383
  • 100
  • 513
  • 979
0

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;
};
cpp
  • 3,743
  • 3
  • 24
  • 38
0

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


    }
}
Mohammad Adnan
  • 6,527
  • 6
  • 29
  • 47
0

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;
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
vaibhav
  • 117
  • 8
  • How is this correct. You are using more than two pointers, its just hidden on the stack every time you do a function call. – Mike G Nov 13 '13 at 08:40
0

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.

Ilian Zapryanov
  • 1,132
  • 2
  • 16
  • 28
0

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

Carl
  • 43,122
  • 10
  • 80
  • 104
0

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;
}
ARC
  • 9
  • 3
  • As clever and undecipherable as that may be, you're in trouble if `sizeof(size_t) < sizeof(ListNode*)`... you should use `std::uintptr_t`. – Quentin Jul 17 '14 at 13:50
0
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);

    }


}
Raju Muke
  • 41
  • 5
0

You can simply reverse a Linked List using only one Extra pointer. And the key to do this is by using a Recursion.

Here is the program in Java.

public class Node {
   public int data;
   public Node next;
}

public Node reverseLinkedListRecursion(Node p) {
    if (p.next == null) {
        head = p;
        q = p;
        return q;
    } else {
        reverseLinkedListRecursion(p.next);
        p.next = null;
        q.next = p;
        q = p;
        return head;
    }
}

// call this function from your main method.
 reverseLinkedListRecursion(head);

As you can see this is a simple example of a head recursion. We have mainly two different kinds of Recursion.

  1. Head Recursion:- When the Recursion is the first thing executed by a function.
  2. Tail Recursion:- When the Recursion is the last thing executed by a function.

Here the program will keep calling itself Recursively until our Pointer "p" reaches to the last node and then before returning the stack frame we will point head to the last node and the extra Pointer "q" to build the linked list in the backward direction.

Here the Stack Frames will keep on returning until the stack is empty.

Nikhil
  • 374
  • 1
  • 4
  • 21
0

Here's a simpler version in python. It does use only two pointers slow & fast

def reverseList(head: ListNode) -> ListNode:

    slow = None
    fast = head
    while fast:  
        node_next = fast.next
        
        fast.next = slow
        slow = fast
            
        fast = node_next
    return slow
Jerry An
  • 1,077
  • 10
  • 18
0

Just use an XOR linked list, which is "naturally reversible" in constant time, by just swapping the first and last (head and tail) pointers.

void reverse() noexcept { std::swap(first_, last_); }

I have uploaded a working example as a project on my GitHub.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
user1095108
  • 14,119
  • 9
  • 58
  • 116
0

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;
    }
}
gevorg
  • 4,835
  • 4
  • 35
  • 52
0

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);
}
Apshir
  • 193
  • 8
0

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;
}
FunBoy
  • 113
  • 2
  • 7
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 ....

}

}
Amit Puri
  • 9
  • 2
-1

You can go for recursive approach:

Here is the pseudo code:

Node* reverse(Node* root)
{
    if(!root) return NULL;

    if(!(root->next)) temp = root;
    else
    {
        reverse(root->next);
        root->next->next = root;
        root->next = NULL;
    }

    return temp;
}

After the call is made to the function, it returns the new root[temp] of the linked list. As it is very clear that it makes use of only two pointers.

gevorg
  • 4,835
  • 4
  • 35
  • 52
Green goblin
  • 9,898
  • 13
  • 71
  • 100
  • @MohdAdnan, did you care understanding the code? The code is to reverse the linked list only. FYI, where did you get the logic for printing the linked list? I don't see any print statement here right? – Green goblin Sep 22 '13 at 16:57
  • Yes Sorry for that. I was suppose to comment on question below and by mistakenly commented here. But Now I just go through the code you wrote and I found one possible flaw . You are not collecting value that is returned by recursive call so I believe that should be changed to temp = reverse(root->next); – Mohammad Adnan Sep 23 '13 at 17:02
  • @MohdAdnan: We don't need to collect the return value of reverse. Please note that temp will be the new root of linked list and we need its return value only in caller function. – Green goblin Jun 15 '16 at 14:01
-1

Solution using 1 variable (Only p):

typedef unsigned long AddressType;

#define A (*( AddressType* )&p )
#define B (*( AddressType* )&first->link->link )
#define C (*( AddressType* )&first->link )

/* Reversing linked list */
p = first;

while( first->link )
{
    A = A + B + C;
    B = A - B - C;
    A = A - B;
    C = A - C;
    A = A - C;
}

first = p;
Vadakkumpadath
  • 1,445
  • 13
  • 21
  • you are using first as a variable (hidden by the fact that you actually use first->link, but still it is a variable.) – njzk2 Apr 01 '14 at 19:58
-6
//with this no extra space and no extra scans but this code is reversing code but read
// in reverse direction no changes made in the linked list 
PrintInReverse(Node node)
{
   // given list is null
   if(node ==null)
       return null;
   // if list contains only one node
   if(node->next ==null)
   {
       print(node.value)
   }
   // call recursively 
   else
   {
       //while(node->next != null)// due to while loop it goes into infinite loop.use //if
       if(node->next!=NULL)
       {
           PrintInReverse(node->next)
           print(node.value)
       }
   }
}

Add comments...
Donal Fellows
  • 133,037
  • 18
  • 149
  • 215