Problem P07. [算法课分治] 链表排序(归并排序)
采用归并算法,先将一个链表分成两个链表,分到不能再分,然后再将已经排好序的链表有序地归并起来。
主要问题:1. 一个子链表如何分成两个。2. 释放空间的问题(没有实现)
#include<iostream>
#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
int n;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
ListNode* mergeAction(ListNode* l, ListNode* r){
ListNode* root = new ListNode();
ListNode* cnt = root;
while (l!=nullptr&&r!=nullptr) {
if (l->val<r->val) {
cnt->next = l;
l = l->next;
}else {
cnt->next = r;
r = r->next;
}
cnt=cnt->next;
}
if (l==nullptr) {
cnt->next = r;
}else {
cnt->next = l;
}
return root->next;
}
ListNode* mergeSort(ListNode* head) {
if (head->next == nullptr){
return head;
}
// 将链表切成两段
ListNode* p = head;
ListNode* q = head;
ListNode* pre = NULL;
while (q != nullptr && q->next != nullptr) {
pre = p;
p = p->next;
q = q->next->next;
}
pre->next = nullptr;
// 递归调用排序方法,将两段进行排序
ListNode* l = mergeSort(head);
ListNode* r = mergeSort(p);
// 将排序后的两段进行合并(merge)
return mergeAction(l, r);
}
int main()
{
ListNode *root = new ListNode();
ListNode *cnt = root;
while (1){
int ret, val;
ret = scanf("%d", &val);
if (ret==EOF){
break;
}
ListNode *next = new ListNode(val);
cnt->next = next;
cnt = cnt->next;
}
root = mergeSort(root->next);
while(root!=nullptr){
printf("%d ", root->val);
root = root->next;
}
return 0;
}