说明
ACM选手请略过,本题用于学习数据结构用。
本程序保证正确:
题目来源:
7-2 两个有序链表序列的合并
分数 20
作者 DS课程组
单位 浙江大学
题目
已知两个非降序链表序列S1与S2,设计函数构造出S1与S2合并后的新的非降序链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出合并后新的非降序链表,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:
1 3 5 -1
2 4 6 8 10 -1
输出样例:
1 2 3 4 5 6 8 10
思路
1. 定义链表结构体。
常规的就可以:
struct ListNode {
int val;
ListNode* next;
ListNode(int x): val(x), next(nullptr) {}
};
2. 为了突出对数据结构的操作,把程序分为读取链表,合并链表,打印链表三个主要部分,最后记得释放内存。
3. 读取链表
用head来存头指针,cur来移动当前节点,newNode用于“制造”新节点。
思想逻辑为(具体细节问题看源代码与注释):
ListNode* newNode = new ListNode(n);
cur->next = newNode;
cur = cur->next;
4. 合并链表
用head存头指针,cur来移动当前节点,l1和l2双指针运动,在比较中遍历两个单链表。
思想逻辑为(具体细节问题看源代码与注释):
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
cur-next = l2;
l2 = l2->next;
}
cur = cur->next;
// 剩余节点
if (l1) {
cur->next = l1;
} else if (l2) {
cur->next = l2;
}
5. 打印链表
简单,就是遍历链表。注意判断列表非空就好了。
思想逻辑为(具体细节问题看源代码与注释):
while (head) {
cout << head->val;
head = head->next;
if (head) cout << " "; //结尾不包含空格
}
释放内存
实际上还是遍历链表。
思想逻辑为(具体细节问题看源代码与注释):
while (mergedList) {
ListNode* temp = mergedList;
mergedList = mergedList->next;
delete temp;
}
源代码
#include <iostream>
using namespace std;
// 节点结构体数据结构
struct ListNode {
int val;
ListNode* next;
ListNode(int x): val(x), next(nullptr) {}
};
// 读取链表
void readList(ListNode*& head) { // 一定要有 & ,引用head,否则就是值传参,函数运行完对head实参无影响。
int n; cin >> n;
ListNode* cur = nullptr;
while (n != -1) {
ListNode* newNode = new ListNode(n);
if (!head) {
head = newNode;
cur = head;
} else {
cur->next = newNode;
cur = cur->next;
}
cin >> n;
}
}
// 打印合并后的链表
void printList(ListNode* head) {
while (head) {
cout << head->val;
head = head->next;
if (head) cout << " ";
}
}
// 合并两个链表
ListNode* mergeSortedList(ListNode* l1, ListNode* l2) {
ListNode* head = nullptr;
ListNode* cur = nullptr;
while (l1 && l2) {
if (l1->val < l2->val) {
// l1 小
if (!head) {
head = l1;
cur = head;
l1 = l1->next;
continue; // 不加就陷入死循环了,一定要加!!!!哥们儿卡在这卡了n多久!!!!!
} else {
cur->next = l1;
l1 = l1->next;
}
} else {
// l2小
if (!head) {
head = l2;
cur = head;
l2 = l2->next;
continue;
} else {
cur->next = l2;
l2 = l2->next;
}
}
cur = cur->next;
} //while
// 剩余节点
if (l1) {
cur->next = l1;
} else if (l2) {
cur->next = l2;
}
return head;
}
int main() {
// 读取两个输入序列
ListNode* l1 = nullptr;
ListNode* l2 = nullptr;
readList(l1);
readList(l2);
// 合并两个链表
ListNode* mergedList = mergeSortedList(l1, l2);
// 打印合并后的链表
if (mergedList) {
printList(mergedList);
} else {
cout << "NULL";
}
// 释放内存
while (mergedList) {
ListNode* temp = mergedList;
mergedList = mergedList->next;
delete temp;
}
return 0;
}