数据结构每日一题day14(链表)★★★★★

题目描述:试编写算法将带头结点的单链表就地逆置,所谓“就地”就是空间复杂度为O(1)。

算法思想:

1.初始化:

定义三个指针 prev、curr、next,分别表示前驱节点、当前节点和后继节点。

prev 初始化为 NULL,curr 初始化为头结点的下一个节点(即第一个有效节点)。

2.遍历链表并反转:

遍历链表,每次将 curr->next 指向 prev,实现局部反转。

然后 prev、curr、next 依次后移,继续处理下一个节点。

3.修正头结点指针:

遍历结束后,prev 指向原链表的最后一个节点,即新链表的第一个节点。

将头结点的 next 指向 prev,完成整个链表的逆置。

复杂度分析:

时间复杂度:O(n)

空间复杂度:O(1)

代码实现:

#include 
#include 

typedef struct Node {
    int data;
    struct Node *next;
} Node, *LinkedList;

// 创建链表(尾插法)
LinkedList createList() {
    LinkedList L = (Node*)malloc(sizeof(Node)), tail = L;
    int x;
    while (scanf("%d", &x), x != -1) {
        tail->next = (Node*)malloc(sizeof(Node));
        tail = tail->next;
        tail->data = x;
    }
    tail->next = NULL;
    return L;
}

// 就地逆置链表
void reverseList(LinkedList L) {
    if (L == NULL || L->next == NULL) {
        return; // 空链表或仅头结点,无需逆置
    }

    Node *prev = NULL;
    Node *curr = L->next; // 第一个有效节点
    Node *next = NULL;

    while (curr != NULL) {
        next = curr->next; // 保存下一个节点
        curr->next = prev; // 反转当前节点的指针
        prev = curr;       // prev 后移
        curr = next;       // curr 后移
    }

    L->next = prev; // 头结点指向新的第一个节点
}

// 打印链表
void printList(LinkedList L) {
    for (Node *p = L->next; p; p = p->next) {
        printf("%d ", p->data);
    }
    puts("");
}

int main() {
    LinkedList L = createList();
    printf("原链表: ");
    printList(L);

    reverseList(L);
    printf("逆置后: ");
    printList(L);

    return 0;
}

你可能感兴趣的:(数据结构,链表)