C 语言中,只使用 两个指针(例如 prev 和 curr)就可以原地反转一个单向链表,虽然通常我们会用三个指针(prev, curr, next),但用两个也可以做到。可以用两个指针(甚至 XOR 技巧)反转单链表,但推荐使用标准的三指针方法来实现,既安全又清晰。

1、使用两个指针反转链表

可以只使用两个指针反转一个单向链表,但逻辑会稍微复杂一点。我们可以通过巧妙地在迭代过程中更新指针,达到反转链表的效果。

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

// 定义节点结构
struct Node {
    int data;
    struct Node* next;
};

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 反转链表(使用两个指针)
struct Node* reverseList(struct Node* head) {
    struct Node* prev = NULL;
    struct Node* curr = head;

    while (curr != NULL) {
        struct Node* next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }

    return prev;
}

// 打印链表
void printList(struct Node* head) {
    struct Node* temp = head;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

// 释放链表
void freeList(struct Node* head) {
    while (head != NULL) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    // 创建链表 1->2->3->4->NULL
    struct Node* head = createNode(1);
    head->next = createNode(2);
    head->next->next = createNode(3);
    head->next->next->next = createNode(4);

    printf("原始链表: ");
    printList(head);

    // 反转链表
    head = reverseList(head);

    printf("反转后的链表: ");
    printList(head);

    // 释放内存
    freeList(head);

    return 0;
}

标准写法略作修改

在每次循环中用一个临时变量交换两个指针的含义,达到节省第三个指针的目的。

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

// 定义节点结构
struct Node {
    int data;
    struct Node* next;
};

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 反转链表(使用两个指针)
struct Node* reverseList(struct Node* head) {
    struct Node* prev = NULL;
    struct Node* curr = head;

    while (curr) {
        curr = (struct Node*)((uintptr_t)curr->next ^ (uintptr_t)prev);
        // 上面是技巧性的 XOR 计算。不是推荐方式。
    }

    return prev;
}


// 打印链表
void printList(struct Node* head) {
    struct Node* temp = head;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

// 释放链表
void freeList(struct Node* head) {
    while (head != NULL) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    // 创建链表 1->2->3->4->NULL
    struct Node* head = createNode(1);
    head->next = createNode(2);
    head->next->next = createNode(3);
    head->next->next->next = createNode(4);

    printf("原始链表: ");
    printList(head);

    // 反转链表
    head = reverseList(head);

    printf("反转后的链表: ");
    printList(head);

    // 释放内存
    freeList(head);

    return 0;
}

2、 更清晰、可读的标准方式(推荐使用三个指针)

使用三个指针 (previous, current, next) 的标准方式通常被认为更清晰和可读,因为它在每一步都显式地维护了当前节点、前一个节点和下一个节点的引用,使得链表的反转过程更加直观易懂。

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

// 定义节点结构
struct Node {
    int data;
    struct Node* next;
};

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 反转链表(三个指针)
struct Node* reverseList(struct Node* head) {
    struct Node* prev = NULL;
    struct Node* curr = head;
    struct Node* next = NULL;

    while (curr != NULL) {
        next = curr->next;   // 暂存下一个节点
        curr->next = prev;   // 反转指针
        prev = curr;         // 向前推进
        curr = next;
    }

    return prev;  // 新的头结点
}



// 打印链表
void printList(struct Node* head) {
    struct Node* temp = head;
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;
    }
    printf("NULL\n");
}

// 释放链表
void freeList(struct Node* head) {
    while (head != NULL) {
        struct Node* temp = head;
        head = head->next;
        free(temp);
    }
}

int main() {
    // 创建链表 1->2->3->4->NULL
    struct Node* head = createNode(1);
    head->next = createNode(2);
    head->next->next = createNode(3);
    head->next->next->next = createNode(4);

    printf("原始链表: ");
    printList(head);

    // 反转链表
    head = reverseList(head);

    printf("反转后的链表: ");
    printList(head);

    // 释放内存
    freeList(head);

    return 0;
}

推荐文档

相关文档

大家感兴趣的内容

随机列表