Tutorial :Reversing Doublely Linked Deque in C



Question:

I'm having trouble reversing my doublely linked deque list (with only a back sentinel) in C, I'm approaching it by switching the pointers and here is the code I have so far:

/* Reverse the deque     param:  q  pointer to the deque   pre: q is not null and q is not empty   post:  the deque is reversed  */  /* reverseCirListDeque */  void reverseCirListDeque(struct cirListDeque *q)  {   struct DLink *back = q->backSentinel;   struct DLink *second = q->backSentinel->prev;   struct DLink *third = q->backSentinel->next;     while (second != q->backSentinel->next){    back->next = second;    third = back->prev;    back->next->prev = back;    back = second;    second = third;   }  }  

But it doesn't seem to work, I've been testing it with a deque that looks like this: 1, 2, 3 The output is: 3 and this process seems to mess up the actual value of the numbers. ie. 2 becomes 2.90085e-309... I think the pointer switching is messed up but I cannot find the problem. And even though it doesn't mean my code is correct; it compiles fine.


Solution:1

If it's a doubly linked list, you shouldn't need to change any pointers at all. Just swap over the payloads:

pointer1 = first  pointer2 = last  while pointer1 != pointer2 and pointer2->next != pointer1:      temp = pointer1->payload      pointer1->payload = pointer2->payload      pointer2->payload = temp      pointer1 = pointer1->next      pointer2 = pointer2->prev  

If by back sentinel you mean the last pointer (as in no first pointer is available), then you need to step backwards throw the deque to find it. It's hard to believe however that this would be the case since it would be a fairly inefficient deque (which is supposed to be a double ended queue).


Solution:2

Linked structures like deques lend themselves readily to recursion, so I tend to favor a recursive style when dealing with linked structures. This also allows us to write it incrementally so that we can test each function easily. Looping as your function does has many downsides: you can easily introduce fencepost errors and it tends toward large functions that are confusing.

First, you've decided to do this by swapping the pointers, right? So write a function to swap pointers:

void swapCirListDequePointers(      struct cirListDeque** left,      struct cirListDeque** right)  {      struct cirListDeque* temp = *left;      *left = *right;      *right = temp;  }  

Now, write a function that reverses the pointers in a single node:

void swapPointersInCirListDeque(struct cirListDeque* q)  {      swapCirListDequePointers(&(q->prev),&(q->next));  }  

Now, put it together recursively:

void reverseCirListDeque(struct cirListDeque* q)  {      if(q == q->backSentinel)          return;        swapPointersInCirListDeque(q);        // Leave this call in tail position so that compiler can optimize it      reverseCirListDeque(q->prev); // Tricky; this used to be q->next  }  

I'm not sure exactly how your struct is designed; my function assumes that your deque is circular and that you'll be calling this on the sentinel.

EDIT: If your deque isn't circular, you'll want to call swapPointersInCirListDeque(q) on the sentinel as well, so move swapPointersInCirListDeque(q) before the if statement.

If you plan to use the backSentinel after this, you should change that also, since it's now the front of the list. If you have a frontSentinel, you can just add swapCirListDequePointers(&(q->frontSentinel),&(q->backSentinel)); to swapPointersInCirListDeque. Otherwise, you'll have to pass in the first node along with q and set q->backSentinel to that.


Solution:3

You've been given a couple of suggestions already; here's another possibility:

// Assumes a node something like:  typedef struct node {       struct node *next, *prev;      int data;  } node;  

and also assumes a couple of variables (globals for the moment) named head and tail that point to the head and tail of the deque, respectively.

void reverse()  {      node *pos = head;      node *temp = pos->next;        head = tail;      tail = pos;        while (pos != NULL) {          node *t = pos->prev;          pos->prev = pos->next;          pos->next = t;          pos = temp;          if (temp)              temp = temp->next;      }     }  

At least for the moment, this does not assume any sentinels -- just NULL pointers to signal the ends of the list.

If you're just storing ints in the deque, Paxdiablo's suggestion is a good one (except that creating a doubly-linked node to hold only an int is a massive waste). Assuming that in reality you were storing something large enough for doubly-linked nodes to make sense, you'd also prefer to avoid moving that data around any more than necessary, at least as a general rule.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »