欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

归并排序 总结

程序员文章站 2022-03-24 13:45:53
...
  • 归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(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;
}