Problem P07. [算法课分治] 链表排序(归并排序)

image

采用归并算法,先将一个链表分成两个链表,分到不能再分,然后再将已经排好序的链表有序地归并起来。
主要问题: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;
}

posted @ 2022-09-05 12:57  白缺  阅读(120)  评论(0编辑  收藏  举报