归并排序 总结
程序员文章站
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;
}