单链表归并排序——时间复杂度O(nlogn),空间复杂度O(1)

如果没有要求空间复杂度为O(1),可以遍历链表并将每个节点的值存入vector中,利用sort( )对vector排序后,最后再遍历一次链表,将排序后的vector中的元素依次赋给链表的节点值。时间复杂度O(nlogn),空间复杂度O(n)。
考点:
1. 归并排序O(nlogn);2. 快慢指针定位链表中间节点。

复杂度分析:
T(n) 拆分 n/2, 归并 n/2 ,一共是n/2 + n/2 = n
/ \ 以下依此类推:
T(n/2) T(n/2) 一共是 n/2*2 = n
/ \ / \
T(n/4) ……….. 一共是 n/4*4 = n

   一共有logn层,故复杂度是 O(nlogn)
#include 
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};
ListNode* mergeSort(ListNode* left, ListNode* right) { //merge时,只改变节点的指向,无需改变任何一个节点的内部值。
    if (left == nullptr && right == nullptr)
        return nullptr;
    ListNode duyy(0);
    ListNode *temp = &duyy;
    while (left != nullptr && right != nullptr) {
        if (left->val > right->val) {
            temp->next = right;
            right = right->next;
        }
        else {
            temp->next = left;
            left = left->next;
        }
        temp = temp->next;
    }
    if (left != nullptr)
        temp->next = left;
    if (right != nullptr)
        temp->next = right;
    return duyy.next;
}
ListNode* sortList(ListNode* head) {
    if (head == nullptr || head->next == nullptr)
        return head;
    ListNode* fast = head->next;
    ListNode* slow = head;
    while (fast != nullptr && fast->next != nullptr) { //快慢指针定位链表中间节点
        slow = slow->next;
        fast = fast->next->next;
    }
    ListNode *left = sortList(slow->next);
    slow->next = nullptr;  //将中间节点的下一个节点指向空,用于merge时表示链表的终点。
    ListNode* right = sortList(head);
    return mergeSort(left, right); //**此处一定是使用sortList()返回的left和right指针**。
}
int main() {
    int n;
    cin >> n;
    ListNode *head = new ListNode(0);
    ListNode *curr = head;
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        ListNode *temp = new ListNode(a);
        curr->next = temp;
        curr = temp;
    }
    head = sortList(head->next);
    while (head != nullptr) {
        cout << head->val << " ";
        head = head->next;
    }
return 0;
}

你可能感兴趣的:(数据结构和算法)