• 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
  • 归并排序分为两步,第一步是将待排序的数分成两部分,将两部分分别有序,再将两个有序的部分合并。
    首先考虑下如何将将二个有序数列合并。这个非常简单,只要从比较二个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果有数列为空,那直接将另一个数列的数据依次取出即可。
  • 将两个有序数列==合并==的时间复杂度为==o(n)==
  • 归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。如何让这二组组内数据有序了?
  • 可以将A,B组各自再分成二组。依次类推,当分出来的小组只有一个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的二个小组就可以了。这样通过先==递归的分解数列,再合并数列==就完成了归并排序。
    归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要==logN步==,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为==O(N*logN)==。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是==效率比较高==的。
  • 快速排序更适用于数组,归并排序更适用于链表。

单链表的归并排序

class Solution {
public:
    ListNode* sortList(ListNode* head) {
        if(!head||!head->next) return head;
        ListNode* mid = findmid(head);
        ListNode* head1 = sortList(head);//递归二分链表
        ListNode* head2 = sortList(mid);
        return merge(head1,head2);
    }
    ListNode* findmid(ListNode* head) {
        ListNode* fast = head,*slow = head,*pre = head;
        while(fast) {
            pre = slow;
            slow = slow->next;
            fast = fast->next?fast->next->next:nullptr;
        }
        pre->next = nullptr;//需要截断链表彻底一分为2
        return slow;
    }
    ListNode* merge(ListNode* head1,ListNode* head2) {
        ListNode* cur1 = head1,*cur2 = head2,* newhead = new ListNode(0),*cur = newhead;
        while(cur1&&cur2) {
            if(cur1->val<=cur2->val) {
                cur->next = cur1;
                cur1 = cur1->next;
            }
            else {
                cur->next = cur2;
                cur2 = cur2->next;
            }
            cur = cur->next;
        }
        cur->next = cur1?cur1:cur2;
        return newhead->next;
    }
};

切记不要返回局部变量的引用和指针

  • c/c++严禁返回局部变量的指针或引用。
  • g++ 和vs编译器 对于这个操作是会有不同的处理
  • vs 不允许读取已经释放的内存空间的内容
  • delete 一个指针之后这个指针的值不会变成nullptr 只是将对应的空间标示为可以被其他程序使用
    -数组当中的归并排序
#include "MergeSort.h"
#include <iostream>

void MergeSort::solution(std::vector<int>& nums) {
    if (nums.size() < 2) return;
    nums = mergesort(0, nums.size() - 1, nums);
    return;
}

vector<int> MergeSort::mergesort(int l, int r, vector<int>& nums) {
    vector<int> temp;
    if (l == r) {
        temp.push_back(nums[l]);
        return temp;
    }
    if (l + 1 == r) {
        if (nums[l] < nums[r]) {
            temp.push_back(nums[l]);
            temp.push_back(nums[r]);
            return temp;
        }
        else {
            temp.push_back(nums[r]);
            temp.push_back(nums[l]);
            return temp;
        }
    }
    int mid = l + (r - l) / 2;
    vector<int> v1 = mergesort(l, mid - 1, nums);
    vector<int> v2 = mergesort(mid, r,nums);
    temp =  merge(v1, v2);
    return temp;
}

vector<int> MergeSort::merge(vector<int>& v1, vector<int>& v2) {
    if (!v1.size()) return v2;
    else if (!v2.size()) return v1;
    vector<int>res;
    int n = v1.size(), m = v2.size(), i = 0, j = 0;
    while (i < n && j < m) {
        if (v1[i] < v2[j]) {
            res.push_back(v1[i]);
            ++i;
        }
        else {
            res.push_back(v2[j]);
            ++j;
        }
    }
    for (; i < n; ++i) {
        res.push_back(v1[i]);
    }
    for (; j < m; ++j) {
        res.push_back(v2[j]);
    }
    return res;
}