归并排序
-
基本思路
归并排序使用分治的思想,每次将数据集分为前后两个部分,直到规模缩减为一,开始合并;合并时通过申请的空间,遍历两个子数据集,将每一个数据从小到大插入,最后将临时数据复制回原序列,直到最后一次得到完整的序列。 -
算法
MERGE(array, begin1, begin2, end):
n1 = begin2-beign1
n2 = end-begin2+1
temp1[n1+1] = MAX
temp2[n2+1] = MAX
for i-n1
temp1[i] = array[begin1+i]
for i-n2
temp[i] = array[begin2+i]
i=0, j=0
for begin1-end
if temp1[i]<temp2[j]
array[begin1] = temp1[i]
begin1++
else
array[begin1] = temp2[j]
begin1++
解释:算法中申请了两个临时的数组,temp1,temp2,分步存放当前数据集的前后两部分(注意它们分别多申请了一个空间存放某个最大值,用作哨兵),之后进行循环,将temp中的数据从小到大插回原序列。
MERGESORT (array, begin, end):
if begin<end:
mid = (begin+end)/2
MERGESORT (array, begin, mid)
MERGESORT (array, mid+1, end)
MERGE (array, begin, mid+1, end)
解释:先递归地分解,然后合并
-
复杂度:O(nlogn)
-
运行截图
-
源代码
#include <iostream>
#include <vector>
#include <ctime>
#include <climits>
using namespace std;
//合并
void Merge(vector<int> &list, int begin1, int begin2, int end);
//归并排序
void MergeSort(vector<int> &list, int begin, int end);
//得到随机序列
void GetRandList(vector<int> &list, int n);
//打印
void Print(const vector<int> &list);
int main(int argc, char** argv) {
vector<int> list;
GetRandList(list,20);
Print(list);
MergeSort(list,0,list.size()-1);
Print(list);
return 0;
}
void Merge(vector<int> &list, int begin1, int begin2, int end)
{
int n1 = begin2-begin1;
int n2 = end-begin2+1;
vector<int> temp1;
vector<int> temp2;
temp1.resize(n1+1);
temp2.resize(n2+1);
temp1[n1] = INT_MAX;
temp2[n2] = INT_MAX;
for(int i=0;i<n1;i++)
{
temp1[i] = list[begin1+i];
}
for(int i=0;i<n2;i++)
{
temp2[i] = list[begin2+i];
}
int i=0;
int j=0;
for(int p=begin1;p<=end;p++)
{
if(temp1[i]<=temp2[j])
list[p] = temp1[i++];
else
list[p] = temp2[j++];
}
}
void MergeSort(vector<int> &list, int begin, int end)
{
if(begin<end)
{
int mid = (begin+end)/2;
MergeSort(list,begin,mid);
MergeSort(list,mid+1,end);
Merge(list,begin,mid+1,end);
}
}
void GetRandList(vector<int> &list, int n)
{
list.resize(n);
for(int i=0;i<n;i++)
{
list[i] = rand()%n;
}
}
void Print(const vector<int> &list)
{
for(int i=0;i<list.size();i++)
{
cout<<list[i]<<" ";
}
cout<<endl;
}