简体   繁体   中英

How do you create a swap function for doubly linked lists?

I'm having issues creating a swap function for a doubly linked list. I want to simply "rewire" the list not change any values (I know this would be easy). I tried to create this temporary item to hold back<-p->front so that I could set q = to this front and back but the temp item changes along with p. How can I swap these items without a temporary item or how do I get my temporary item to behave.

void DLinkedList::swap(Item *p, Item *q)
{
    Item* temp = p;
    p->next = q->next;
    p->pre = q->pre;
    if (p->next != NULL)
        p->next->pre = p;
    if (q->next != NULL)
        q->next->pre = q;
    q->next = temp->next;
    q->pre = temp->pre;
    if (p->pre != NULL)
        p->pre->next = p;
    if (!q->pre == NULL) {
        q->pre->next = q;
    }
    cout << "- The items " << p->val << " & " << q->val << " were swapped -" << endl;
}

Here's the situation in pictorial form:

+----------+       +----------+       +----------+
| before_p |  <->  |     p    |  <->  | after_p  |
+----------+       +----------+       +----------+

+----------+       +----------+       +----------+
| before_q |  <->  |     q    |  <->  | after_q  |
+----------+       +----------+       +----------+

The problem you have is that saving a temp pointer to p does not actually copy the pointers inside p . So when you overwrite them, you're in trouble.

Now, those "before" and "after" items in the picture are what you really want. It's much easier to just copy them out and then do the logic. Look at how much clearer the following code is:

Item * before_p = p->pre;
Item * before_q = q->pre;
Item * after_p = p->next;
Item * after_q = q->next;

// Relink before and after nodes
if( before_p ) before_p->next = q;
if( before_q ) before_q->next = p;
if( after_p ) after_p->pre = q;
if( after_q ) after_q->pre = p;

// Relink nodes themselves
p->pre = before_q;
q->pre = before_p;
p->next = after_q;
q->next = after_p;

You may also want a sanity test before you do anything :

if( p == q || !p || !q ) return;

And finally, if you are maintaining a pointer to the head of your list somewhere, and that happens to be one of the items swapped, don't forget to update it after*.

if( head == p ) head = q;
else if( head == q ) head = p;

(*) Same goes for other pointers like tail .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM