📌  相关文章
📜  用于交换链表中的节点而不交换数据的 C 程序(1)

📅  最后修改于: 2023-12-03 15:27:10.151000             🧑  作者: Mango

用于交换链表中的节点而不交换数据的 C 程序

在链表中,交换两个节点的指针常常需要交换节点的数据,但有时我们需要仅仅交换节点指针,而不改变节点数据。本文介绍一种用于交换链表中节点指针而不改变节点数据的 C 程序。

原理

在链表中交换两个节点的指针,需要修改它们各自前面节点的指针和它们各自的后面节点的指针,如下图所示:

prev1 -> node1 -> next1 -> node2 -> next2

交换 node1 和 node2 的指针后:

prev1 -> node2 -> next1 -> node1 -> next2

但如果我们需要仅仅交换节点指针,不改变节点数据,我们就不能修改节点指针所指向的数据,因为这会改变链表中各个节点的数据。但是,我们可以使用指向指针的指针(或者叫二级指针)来实现这个目标。具体来说,我们将指向 node1 的指针指针(即 prev1->next 或者 next1->prev)和指向 node2 的指针指针(即 node2->prev 或者 node1->next)互相交换,这样就能够交换节点指针而不改变节点数据了。

代码

下面是一个用于交换链表中节点指针而不改变节点数据的 C 程序的代码,其中的 swap_nodes 函数接受一个指向头节点的指针的指针、两个待交换的节点的值,返回交换后的头节点指针的指针。

#include <stdio.h>
#include <stdlib.h>

struct node {
    int data;
    struct node* next;
    struct node* prev;
};

void print_list(struct node* head) {
    while (head != NULL) {
        printf("%d ", head->data);
        head = head->next;
    }
    printf("\n");
}

struct node* create_list(int* arr, int n) {
    struct node *head, *tail, *p;
    head = tail = NULL;
    for (int i = 0; i < n; i++) {
        p = (struct node*) malloc(sizeof(struct node));
        p->data = arr[i];
        p->prev = tail;
        p->next = NULL;
        if (tail != NULL)
            tail->next = p;
        else
            head = p;
        tail = p;
    }
    return head;
}

struct node** swap_nodes(struct node** head_ref, int x, int y) {
    if (x == y)
        return head_ref;

    struct node **p1 = NULL, **p2 = NULL, **prev1 = NULL, **prev2 = NULL;

    /* Find pointers to nodes x, y and their previous nodes */
    p1 = head_ref;
    while (*p1 != NULL && (*p1)->data != x) {
        prev1 = p1;
        p1 = &((*p1)->next);
    }
    p2 = head_ref;
    while (*p2 != NULL && (*p2)->data != y) {
        prev2 = p2;
        p2 = &((*p2)->next);
    }

    /* Do the actual swapping */
    if (*p1 != NULL && *p2 != NULL) {
        /* Swap the next pointers */
        struct node* tmp = (*p1)->next;
        (*p1)->next = (*p2)->next;
        (*p2)->next = tmp;

        /* Swap the prev pointers */
        tmp = (*p1)->prev;
        (*p1)->prev = (*p2)->prev;
        (*p2)->prev = tmp;

        /* Fix the pointers of the nodes before x and y */
        if (prev1 != NULL)
            (*prev1)->next = *p2;
        else
            *head_ref = *p2;

        if (prev2 != NULL)
            (*prev2)->next = *p1;
        else
            *head_ref = *p1;

        /* Swap the pointers of x and y */
        tmp = *p1;
        *p1 = *p2;
        *p2 = tmp;
    }

    return head_ref;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr) / sizeof(arr[0]);
    struct node* head = create_list(arr, n);
    printf("Originally: ");
    print_list(head);

    /* Swap nodes 2 and 4 */
    head = *swap_nodes(&head, 2, 4);
    printf("After swapping: ");
    print_list(head);

    return 0;
}
总结

本文介绍了一种用于交换链表中节点指针而不改变节点数据的 C 程序。这个程序利用指向指针的指针(或者叫二级指针)来实现交换节点指针而不改变节点数据,具有一定的实用价值。