3

I've been trying to figure out how to reverse the order of a doubly-linked list, but for some reason, in my function void reverse() runs while loop once and then crashes for some reason. To answer some questions ahead, I'm self-teaching myself with my brothers help. This isn't all of the code, but I have a display() function which prints all nodes chronologically from start_ptr and a switch which activates certain functions like

    case 1 : add_end(); break;
    case 2 : add_begin(); break;
    case 3 : add_index(); break;
    case 4 : del_end(); break;
    case 5 : del_begin(); break;
    case 6 : reverse(); break;

This is the geist of my code:

#include <iostream>
using namespace std;

struct node
{
    char name[20];
    char profession[20];
    int age;
    node *nxt;
    node *prv;
};

node *start_ptr = NULL;

void pswap (node *pa, node *pb)
{
    node temp = *pa;
    *pa = *pb;
    *pb = temp;
    return;
}

void reverse()
{
    if(start_ptr==NULL)
    {
        cout << "Can't do anything" << endl;
    }
    else if(start_ptr->nxt==NULL)
    {
        return;
    }
    else
    {
        node *current = start_ptr;
        node *nextone = start_ptr;
        nextone=nextone->nxt->nxt;
        current=current->nxt;
        start_ptr->prv=start_ptr->nxt;
        start_ptr->nxt=NULL;
        //nextone=nextone->nxt;
        while(nextone->nxt!= NULL)
        {
            pswap(current->nxt, current->prv);
            current=nextone;
            nextone=nextone->nxt;
        }
        start_ptr=nextone;
    }
}
2
  • 2
    You're swapping the contents of the nodes rather than just the node pointers. Are you sure you want to do that? Commented Jul 7, 2010 at 20:43
  • On a related note, you could look at the things from a different point of view. Rather than reverse the contents of the doubly-linked list itself, you could instead focus on iterating over the contents of the list in reverse, which should be straightforward since the list is doubly-linked. For example, implement STL-style bidirectional iterators for your list. They can be used with the std::reverse_iterator<> adapter (for rbegin() and rend()). Once those methods are implemented it'll be simple to leverage the STL algorithms, including std::reverse(). It's a fun exercise, IMO. Commented Jul 7, 2010 at 23:42

10 Answers 10

7

Try this:

node *ptr = start_ptr;
while (ptr != NULL) {
    node *tmp = ptr->nxt;
    ptr->nxt = ptr->prv;
    ptr->prv = tmp;
    if (tmp == NULL) {
        end_ptr = start_ptr;
        start_ptr = ptr;
    }
    ptr = tmp;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Best one, though I'm having a brain fart because you didn't end the list with the pointer addressed to NULL
Wow, thanks a lot man, I fixed your code up a bit and it looks so much prettier than all my other attempts. All you had to do was add a qualification when start_ptr==NULL || start_ptr->nxt==NULL and make your part of the code the else end. Within that, I made sure at the end code, end_ptr->nxt=NULL; Thanks a bunch
I'm not really sure why you need those checks - I think the code I gave will work fine without them. And at the end, end_ptr->nxt will be NULL because at the start, start_ptr->prv was NULL. But you're welcome, at any rate.
@Borealid can't we just assign head pointer to the last node and NULL to prv of starting node?
@Dan : I know 9 years have passe, but - end_ptr is not defined anywhere. Did you make that change?
3

EDIT: My first implementation, which was correct but not perfect. Your implementation is pretty complicated. Can you try this instead:

node * reverse(Node * start_ptr)
{
    Node *curr = start_ptr; 
    Node * prev = null;
    Node * next = null;
    while(curr)
    {
        next = curr->nxt;
        curr->nxt = prev;
    curr->prv = next;
        prev = curr;
        curr = next;
    }
    return start_ptr=prev;
}

Here is my updated solution:

node * reverse()
{
    node *curr = start_ptr; 
    node * prev = NULL;
    node * next = NULL;
    while(curr)
    {
        next = curr->nxt;
        curr->nxt = prev;
        curr->prv = next;
        prev = curr;
        curr = next;
    }
    return start_ptr=prev;
}

The logic was correct. But the issue was that I was accepting in input argument start_ptr. Which means that I was returning the local copy of it. Now it should be working.

2 Comments

I just can't figure out how I might be doing that. Can anyone confirm if this implementation creates a circular linked list? Thanks...
Hi Danutenshu, I have updated my solution. I know your issues is already solved, but I would feel much better if you can please let me know if what I have changed is correct?
2

You can simplify your reverse() quite a bit. I'd do something like this:

void reverse()
{
    if(start_ptr == NULL)
    {
        cout << "Can't do anything" << endl;
    }
    else
    {
        node *curr = start_ptr;
        while(curr != NULL)
        {
            Node *next = curr->next;
            curr->next = curr->prev;
            curr->prev = next;
            curr = next;
        }
        start_ptr = prev;       
    }
}

Explanation: The basic idea is simply to visit each Node and swap the links to previous and next. When we move curr to the next Node, we need to store the next node so we still have a pointer to it when we set curr.next to prev.

2 Comments

I think you missed updating the first node's prev to be the second node.
Indeed, and I was off-by-one at the start. Should be better now.
1

Simple solution. reverses in less than half a number of total iterations over the list

template<typename E> void DLinkedList<E>::reverse() {
    int median = 0;
    int listSize = size();
    int counter = 0;

    if (listSize == 1)
    return;

    DNode<E>* tempNode = new DNode<E>();

    /**
     * A temporary node for swapping a node and its reflection node
     */
    DNode<E>* dummyNode = new DNode<E>();

    DNode<E>* headCursor = head;
    DNode<E>* tailCursor = tail;

    for (int i = 0; i < listSize / 2; i++) {
        cout << i << "\t";

        headCursor = headCursor->next;
        tailCursor = tailCursor->prev;

        DNode<E>* curNode = headCursor;
        DNode<E>* reflectionNode = tailCursor;

        if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
            /**
             * insert a dummy node for reflection
         * for even sized lists
         */
        curNode->next = dummyNode;
        dummyNode->prev = curNode;

        reflectionNode->prev = dummyNode;
        dummyNode->next = reflectionNode;

    }
    /**
     * swap the connections from previous and 
             * next nodes for current and reflection nodes
     */

    curNode->prev->next = curNode->next->prev = reflectionNode;

    reflectionNode->prev->next = reflectionNode->next->prev = curNode;

    /**
     * swapping of the nodes
     */

    tempNode->prev = curNode->prev;
    tempNode->next = curNode->next;

    curNode->next = reflectionNode->next;
    curNode->prev = reflectionNode->prev;

    reflectionNode->prev = tempNode->prev;
    reflectionNode->next = tempNode->next;

    if (listSize % 2 == 0 && listSize / 2 - 1 == i) {
        /**
         * remove a dummy node for reflection
         * for even sized lists
         */
        reflectionNode->next = curNode;
        curNode->prev = reflectionNode;
    }

    /**
     * Reassign the cursors to position over the recently swapped nodes
     */
        tailCursor = curNode;
        headCursor = reflectionNode;

    }

    delete tempNode, dummyNode;
}

template<typename E> int DLinkedList<E>::size() {
    int count = 0;
    DNode<E>* iterator = head;

    while (iterator->next != tail) {
        count++;
        iterator = iterator->next;
    }
    return count;
}

Comments

0

I suggest maintaining a link to the last node.
If not, find the last node. Traverse the list using the "previous" links (or in your case, prv).

There is no need to actually change the links around. Traversing using the prv pointer will automatically visit the nodes in reverse order.

Comments

0

Look at

valuesnextone=nextone->nxt->nxt;

Here nextone->nxt can be null.

Apart from that, try to use pointers to pointers in the swap function.

Comments

0

Your pswap function is wrong your should swap the pointer not try to create temporary objects and swap them. Should be like that (there might be other mistake later)

void pswap (node *&pa, node *&pb)
{
    node* temp = pa;
    pa = pb;
    pb = temp;
    return;
}

2 Comments

That won't actually do anything. You need to pass pointers to pointers or references to pointers so the changes apply to the original objects, not local copies.
you are absolutely right, I didn't look at the signature function. Just fixed the temporary object creation mistake
0

A very simple and O(n) solution using two pointers:

start = head of the doubly LL

struct node *temp, *s;
s = start;

while(s != NULL){
  temp = s->prev;
  s->prev = s->next;
  s->next = temp;
  s = s->prev;
}

//if list has more than one node
if(current != NULL){
  start = temp->prev;
}

Comments

0

My code for reversing doubly linked list,

Node* Reverse(Node* head)
{
// Complete this function
// Do not write the main method. 


if(head != NULL) {

    Node* curr = head;
    Node* lastsetNode = curr;
    while(curr != NULL) {

        Node* frwdNode = curr->next;
        Node* prevNode = curr->prev;


        if(curr==head) {                
            curr->next = NULL;
            curr->prev = frwdNode;
            lastsetNode = curr;
        }
        else {
            curr->next = lastsetNode;
            curr->prev = frwdNode;
            lastsetNode = curr;
        }



        curr = frwdNode;
    }

    head = lastsetNode;
}


return head;
}

Comments

0

I thought I'd add a recursive solution here.

node* reverse_and_get_new_head(node* head) {
    if (head == nullptr) { return nullptr; } 
      // This can be avoided by ensuring the initial,
      // outer call is with a non-empty list
    std::swap(head->prev, head->next);
    if (head->prev == nullptr) { return head; }
    return reverse_and_get_new_head(head->prev);
}

void reverse() {
    start_ptr = reverse_and_get_new_head(start_ptr);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.