如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。
归并排序不管什么情况时间复杂度都是O(nlogn),但是其空间复杂度为O(n)。如代码中用来进行归并的数组guodu,归并排序两个数组的合并需要一个额外的数组来进行过渡,相当于数组1和数组2合并,开一个数组3空间大小为数组1加数组2。数组1、2从头开始比较,将较小元素放至数组3。
正是因为其需要开辟一块额外的空间(如排序30G数据的话,30G的内存空间还是比较困难的),所以其日常应用不如快排。虽然快排的时间复杂度是O(nlogn)(平均),最坏时间复杂度是O(n^2)。下一篇博客我就会给大家讲一下快排的实现。
实现代码:
#include <iostream>
#include <vector>
using namespace std;
vector<int> combine(vector<int>& nums,int head,int middle,int rear)
{
// debug用
// cout<<"-----------------------------------------------"<<endl;
// for(int b=0;b<nums.size();b++)
// {
// cout<<nums[b]<<" ";
// }
// cout<<endl;
vector<int> guodu;
guodu=nums;
int i=middle-head+1;
int j=rear-middle;
int first=0;
int second=0;
while(first<i&&second<j)
{
if(guodu[head+first]<=guodu[middle+1+second])
{
nums[head+first+second]=guodu[head+first];
first++;
}
else
{
nums[head+first+second]=guodu[middle+1+second];
second++;
}
}
if(first==i)
{
int second1=second;
for(int n=0;n<j-second1;n++)
{
nums[head+first+second]=guodu[middle+1+second];
second++;
}
}
else
{
int first1=first;
for(int n=0;n<i-first1;n++)
{
nums[head+first+second]=guodu[head+first];
first++;
}
}
// debug用
// cout<<"head="<<head<<"--middle="<<middle<<"--rear="<<rear<<endl;
// for(int a=0;a<nums.size();a++)
// {
// cout<<nums[a]<<" ";
// }
// cout<<endl<<"-----------------------------------------------"<<endl;
// cout<<endl;
return nums;
}
void mergeSort(vector<int>& nums,int head,int rear)
{
if(head>=rear)
{
return;
}
else
{
int middle=(head+rear)/2;
mergeSort(nums,head,middle);
mergeSort(nums,middle+1,rear);
combine(nums,head,middle,rear);
}
}
int main()
{
vector<int> test;
test.push_back(5);
test.push_back(13);
test.push_back(13);
test.push_back(7);
test.push_back(19);
test.push_back(12);
test.push_back(4);
test.push_back(6);
test.push_back(1);
test.push_back(2);
test.push_back(3);
test.push_back(8);
for(int i=0;i<test.size();i++)
{
cout<<test[i]<<" ";
}
cout<<endl;
int qsize=test.size();
mergeSort(test,0,qsize-1);
for(int i=0;i<test.size();i++)
{
cout<<test[i]<<" ";
}
return 0;
}