typedef struct Node { int data; struct Node* next; } Node; Node* reverseList(Node* head) { Node *prev = NULL, *current = head, *next = NULL; while (current) { next = current->next; current->next = prev; prev = current; current = next; } return prev; } Node* mergeLists(Node* a, Node* b) { Node dummy = {0, NULL}; Node* tail = &dummy; while (a && b) { if (a->data >= b->data) { tail->next = a; a = a->next; } else { tail->next = b; b = b->next; } tail = tail->next; } tail->next = a ? a : b; return dummy.next; } Node* createList(int arr[], int n) { Node dummy = {0, NULL}; Node* tail = &dummy; for (int i = 0; i < n; i++) { tail->next = (Node*)malloc(sizeof(Node)); tail = tail->next; tail->data = arr[i]; tail->next = NULL; } return dummy.next; } void printList(Node* head) { while (head) { printf("%d ", head->data); head = head->next; } printf("\n"); } int main() { int arrA[] = {2, 2, 3}; int arrB[] = {1, 3, 4}; Node* LA = createList(arrA, 3); Node* LB = createList(arrB, 3); LA = reverseList(LA); LB = reverseList(LB); Node* LC = mergeLists(LA, LB); printList(LC); return 0; }
时间: 2025-07-08 20:27:06 浏览: 14
<think>嗯,用户想了解如何在C语言中实现链表的反转和有序合并函数。首先,我需要回忆一下链表的基本操作,以及这两个功能的具体实现方法。反转链表和合并有序链表都是常见的数据结构问题,但具体到C语言的实现,可能需要注意指针的操作和内存管理。
对于链表反转,我记得有两种方法:迭代和递归。迭代法需要三个指针,分别指向前一个节点、当前节点和下一个节点。通过遍历链表,逐个改变节点的指向。而递归法则是将问题分解为反转子链表,然后处理当前节点。不过递归可能会有栈溢出的风险,特别是链表很长的时候,但代码可能更简洁。
然后是合并两个有序链表。这通常也是用迭代或递归的方法。迭代法需要创建一个哑节点作为新链表的起始点,然后比较两个链表的当前节点值,依次连接较小的节点。递归法则比较两个头节点,将较小的节点作为合并后的头,然后递归处理剩下的部分。
用户提到了优化,可能需要考虑代码的时间复杂度和空间复杂度。比如,递归虽然简洁,但空间复杂度是O(n)因为递归栈,而迭代法是O(1)空间。另外,处理链表时要注意指针的正确移动,避免出现空指针解引用。
现在需要检查提供的引用内容。根据引用[1]和[3],递归反转链表的方法是假设剩余部分已经反转,然后处理当前节点。合并有序链表的递归方法在引用[2]、[3]、[4]中有示例,比较两个链表的头节点,递归连接较小的节点。
用户要求用C语言实现,所以需要将示例中的C++代码转换为C。比如,处理结构体指针,使用malloc分配内存,但注意用户可能不需要完整的程序,而是函数实现。
在写代码时,需要注意指针的操作,比如反转链表时的指针指向,合并时的节点连接。同时,考虑边界情况,比如空链表、单节点链表等。
可能遇到的问题包括内存泄漏、指针丢失、循环链表等。比如,在反转链表时,如果不保存下一个节点的指针,可能会丢失后续链表。在合并时,需要处理一个链表遍历完的情况,将另一个链表剩余部分直接连接。
对于优化,可以讨论迭代法和递归法的选择,根据具体情况判断。比如,如果链表很长,迭代法更安全;如果链表较短,递归法代码更简洁。另外,合并有序链表时,可以选择不使用哑节点,而是直接比较头节点,但使用哑节点可以简化代码。
总结一下,实现步骤:
反转链表:
1. 迭代法:使用三个指针,prev, current, next,逐个反转指向。
2. 递归法:递归到链表末尾,然后逐层返回,调整指针。
合并有序链表:
1. 迭代法:创建哑节点,比较两个链表的当前节点,依次连接。
2. 递归法:比较头节点,递归处理剩余部分,返回较小的节点。
在代码中要注意结构体的定义,比如链表节点的结构体包含数据和next指针。在C语言中没有类的概念,所以函数需要接受节点指针作为参数,并返回新的头节点。
测试案例方面,可以举例如反转1->2->3->4得到4->3->2->1,合并1->2->4和1->3->4得到1->1->2->3->4->4,如引用[4]中的示例。
最后,需要将思考整理成步骤清晰的解释,并提供代码示例,同时回答相关问题,比如优化方法、应用场景等,如用户提供的示例中的结构。</think>### C语言链表反转与有序合并实现
#### 一、链表反转实现
##### (1) 迭代法实现
```c
struct ListNode {
int val;
struct ListNode* next;
};
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode *prev = NULL, *curr = head;
while (curr != NULL) {
struct ListNode* nextTemp = curr->next;
curr->next = prev; // 反转指针方向
prev = curr; // 前指针后移
curr = nextTemp; // 当前指针后移
}
return prev;
}
```
*时间复杂度$O(n)$,空间复杂度$O(1)$*
##### (2) 递归法实现
```c
struct ListNode* reverseListRecursive(struct ListNode* head) {
if (head == NULL || head->next == NULL)
return head;
struct ListNode* newHead = reverseListRecursive(head->next);
head->next->next = head; // 反向连接节点
head->next = NULL; // 断开原连接
return newHead;
}
```
*时间复杂度$O(n)$,空间复杂度$O(n)$(递归栈)*
#### 二、有序链表合并实现
##### (1) 迭代法实现
```c
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
struct ListNode dummy; // 哑节点简化操作
struct ListNode* tail = &dummy;
while (l1 && l2) {
if (l1->val < l2->val) {
tail->next = l1;
l1 = l1->next;
} else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}
tail->next = l1 ? l1 : l2; // 连接剩余链表
return dummy.next;
}
```
*时间复杂度$O(n+m)$,空间复杂度$O(1)$*
##### (2) 递归法实现
```c
struct ListNode* mergeTwoListsRecursive(struct ListNode* l1, struct ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
if (l1->val < l2->val) {
l1->next = mergeTwoListsRecursive(l1->next, l2);
return l1;
} else {
l2->next = mergeTwoListsRecursive(l1, l2->next);
return l2;
}
}
```
*时间复杂度$O(n+m)$,空间复杂度$O(n+m)$(递归栈)*
#### 三、关键优化技巧
1. **尾指针优化**:在迭代合并中使用尾指针直接连接剩余链表,避免重复遍历
2. **哑节点技巧**:避免处理头节点特殊情况的复杂判断
3. **递归终止条件**:在递归法中必须严格判断链表为空的情况
4. **指针安全操作**:所有指针操作前必须进行非空判断,如:
```c
while (curr != NULL) { // 安全遍历条件
struct ListNode* next = curr->next;
// ...操作...
}
```
#### 四、测试案例
1. **反转测试**:输入`1->2->3->4`,输出`4->3->2->1`
2. **合并测试**:输入`1->2->4`和`1->3->4`,输出`1->1->2->3->4->4`[^4]
阅读全文
相关推荐



















