合并有序链表 - 问题与解决总结
1. 指针访问错误:cur->next->val = list1->val;
- 问题:
->
用于指针访问,如果next
或list1
不是指针或为空,就会报错。 -
解决:
-
保证结构体中
next
定义为指针:struct ListNode { int val; ListNode* next; };
-
对非指针变量用
.
,对指针用->
;访问前要检查指针非空。
-
2. 循环条件错误:while (list1 || list2)
vs while (list1 && list2)
||
情况:当任一链表非空都会进入循环,可能把空指针通过->
访问,或先拼接完一个再拼另一个,破坏有序性。&&
情况:仅在两条链都未走完时循环,保证每次都能安全比较并接入较小节点;循环结束后再统一挂上剩余节点。
3. 空指针解引用运行时错误
-
错误示例:
runtime error: member access within null pointer of type 'ListNode'
表明在
nullptr->val
或nullptr->next
时触发未定义行为。 -
防范:任何
ptr->成员
前,都要确保ptr != nullptr
。
4. ->
与 .
运算符
运算符 | 用法 | 对象类型 | 示例 |
---|---|---|---|
. |
对象或引用访问成员 | 非指针实例 | a.val |
-> |
指针访问所指对象成员 | 指针 | p->val 等价于 (*p).val |
完整可执行示例代码
下面示例通过标准输入读取两个有序链表的长度及元素,合并后输出结果。保证所有空指针访问前均已检查。
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode(int x): val(x), next(nullptr) {}
};
// 合并两个有序链表
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* cur = &dummy;
while (l1 && l2) {
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
cur->next = l1 ? l1 : l2;
return dummy.next;
}
int main() {
int n;
cin >> n;
ListNode* l1 = nullptr;
ListNode* tail = nullptr;
for (int i = 0; i < n; ++i) {
int x; cin >> x;
if (!l1) l1 = tail = new ListNode(x);
else { tail->next = new ListNode(x); tail = tail->next; }
}
int m;
cin >> m;
ListNode* l2 = nullptr;
tail = nullptr;
for (int i = 0; i < m; ++i) {
int x; cin >> x;
if (!l2) l2 = tail = new ListNode(x);
else { tail->next = new ListNode(x); tail = tail->next; }
}
ListNode* merged = mergeTwoLists(l1, l2);
bool first = true;
while (merged) {
if (!first) cout << ' ';
cout << merged->val;
first = false;
merged = merged->next;
}
cout << endl;
return 0;
}