将不带头节点的单推态所有结点的连接方向“原地”逆转,即要求利用原表的存价空间。
时间: 2024-09-29 21:10:21 浏览: 36
要将一个不带头节点的单链表的所有节点的连接方向逆转,也称为反转链表(Reverse Linked List),你需要遍历链表并修改每个节点的指针,使其指向前一个节点。这可以通过迭代或递归的方式实现,但都需要在原地操作,即只使用常数额外的空间。
**迭代方法(原地)**:
```c
struct ListNode {
int val;
struct ListNode *next;
};
void reverseList(struct ListNode **head) {
if (*head == NULL || (*head)->next == NULL) {
return; // 基线条件:空链表或只有一个节点
}
struct ListNode *prev = NULL, *curr = *head;
while (curr != NULL) {
// 保存当前节点的下一个节点
struct ListNode *temp = curr->next;
// 修改当前节点的next指向前一个节点
curr->next = prev;
// 更新prev和curr为下一个节点
prev = curr;
curr = temp;
}
*head = prev; // 最后,头节点变为原链表的尾节点
}
```
在这个代码中,`prev` 指向当前节点的前一个节点,初始时 `prev` 为 `NULL`,而 `curr` 初始指向 `head`。每次循环,我们都先保存 `curr` 的下一个节点,然后让 `curr` 指向 `prev`,再更新 `prev` 和 `curr` 进行下一轮循环。当 `curr` 变成 `NULL` 时,`prev` 就变成了新的头节点。
**递归方法(不是原地,但也可以考虑用栈空间替换)**:
```c
void reverseListRecursive(struct ListNode *head, struct ListNode **prev) {
if (head == NULL) {
*prev = head; // 当到达最后一个节点时,将其设置为新的头
} else {
struct ListNode *next = head->next;
head->next = *prev;
reverseListRecursive(next, &head); // 递归调用处理剩余的部分
}
}
// 调用时传递头节点和一个临时指针(初始化为NULL)
reverseListRecursive(head, &head);
```
这里递归版本的工作原理是把子问题分解为两个部分:处理当前节点和处理其后的节点。但在递归中,我们通常不能直接控制存储空间,所以这不是严格意义上的原地操作。
阅读全文