swap in doubly linked list

回眸只為那壹抹淺笑 提交于 2019-12-02 01:19:32

The code will fail if ptr1 == head (ptr1->prev == NULL) or ptr2 == head (ptr2->prev == NULL), because it ends up trying to use head->next, which doesn't exist. There also needs to be a check for the end of a list, if ptr1->next == NULL or ptr2->next == NULL, which can be handled using a local tail pointer. Using pointers to pointer to node can simplify the code. For example the pointer to next pointer to ptr1 could be &ptr1->prev->next or &head. The pointer to prev pointer to ptr2 could be &ptr2->next->prev or &tail (and set tail = ptr2).

Using pointers to pointer to node fixes the issue with swapping adjacent nodes. Also temp can be a pointer to node.

Example code using pointers to nodes (instead of counts) to swap:

typedef struct node NODE;
/* ... */
NODE * SwapNodes(NODE *head, NODE *ptr1, NODE *ptr2)
{
NODE **p1pn;            /* & ptr1->prev->next */
NODE **p1np;            /* & ptr1->next->prev */
NODE **p2pn;            /* & b->prev->next */
NODE **p2np;            /* & b->next->prev */
NODE *tail;             /* only used when x->next == NULL */
NODE *temp;             /* temp */
    if(head == NULL || ptr1 == NULL || ptr2 == NULL || ptr1 == ptr2)
        return head;
    if(head == ptr1)
        p1pn = &head;
    else
        p1pn = &ptr1->prev->next;
    if(head == ptr2)
        p2pn = &head;
    else
        p2pn = &ptr2->prev->next;
    if(ptr1->next == NULL){
        p1np = &tail;
        tail = ptr1;
    } else
        p1np = &ptr1->next->prev;
    if(ptr2->next == NULL){
        p2np = &tail;
        tail = ptr2;
    }else
        p2np = &ptr2->next->prev;
    *p1pn = ptr2;
    *p1np = ptr2;
    *p2pn = ptr1;
    *p2np = ptr1;
    temp = ptr1->prev;
    ptr1->prev = ptr2->prev;
    ptr2->prev = temp;
    temp = ptr1->next;
    ptr1->next = ptr2->next;
    ptr2->next = temp;
    return head;
}

This can be compacted, but if you are having problems, it can help to spell it out in detail.

typedef struct node Node;

void link( Node* a, Node* b )
{
    a->next = b;
    b->prev = a;
}

void swap_nodes( Node* a, Node* b )
{
    if(a==b) return; // don't swap with yourself

    // handle adjacent nodes separately
    if( a->next == b )
    {
        Node* bef = a->prev;
        Node* aft = b->next;
        link( bef, b);    // link bef, b, a, aft
        link( b, a );
        link( a, aft );
    }
    else if( b->next == a )
    {
        Node* bef = b->prev;
        Node* aft = a->next;
        link( bef, a);   // link bef, a, b, aft
        link( a, b );
        link( b, aft );
    }
    else
    {
        Node* a_prv = a->prev;
        Node* a_nxt = a->next;
        Node* b_prv = b->prev;
        Node* b_nxt = b->next;

        link( a_prv, b ); link( b, a_nxt ); // links b in a's old position
        link( b_prv, a ); link( a, b_nxt ); // links a in b's old position
    }
}

Also note that your head node should never be null, it should be a sentry node that links to itself if your list is empty. This means that there are never a first node, nor a last, nor is the list ever empty. This removes a ton of special cases. See here

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!