版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xnh_565175944/article/details/82828432
合并排序是用分治策略的一个排序算法。
其基本思想是将待排序元素分成大小大致相同的两个子序列,对两个子序列进行排序后,再进行合并。
通俗来讲,待排序元素不停的分解与合并,这是一个重复且相似的过程。
假设有n个元素,我们将其划分两半,再对其中的一部分再划分两半,重复此操作,直至最小序列长度为2或3的时候,我们对最小序列进行分解按大小合并,我们就得到一个排序成功的最小子序列,再将其与同级的最小子序列(已经做了同样操作排过序)进行按大小合并。重复此操作,直到 n/2长度的序列与n/2长度的序列合并,合并排序算完成。
merge函数 用来合并p-q 与 q-r 两个长度序列(按照递增序列)
void merge(int num[],int p,int q,int r)
{
int n1 = q - p + 1; //前半段的长度
int n2 = r - q + 1; //后半段的长度
int left[n1+1], right[n2];
for(int i = 0; i < n1;++i)
left[i] = num[p + i]; //将前半段复制到左边
left[n1] = 65536; //最后一位设置为大值防止排序时出错
for(int j = 0; j < n2; ++j)
right[j] = num[q + j + 1]; //将后半段复制到右边
right[n2-1] = 65536;
int i = 0,j = 0;
for(int x = p ; x <= r; x++ ) //将左右合并
{
if (left[i] < right[j])
{
num[x] = left[i++];
}
else
{
num[x] = right[j++];
}
}
}
mergeSort函数 划分区域
void mergeSort(int num[],int p,int r)
{
if(p < r) //当p=r的时候说明只有1个元素,最低也要有2个元素
{
int q = (p + r) / 2; //划分位置
mergeSort(num, p, q); //将左边进行归并排序
mergeSort(num, q+1, r); //将右边进行归并排序
merge(num, p, q, r); //将左右合并
}
}
时间复杂度:
因为每次会分成大致均等的两部分,所以对于n个元素,它大概会合并O(log₂n)次,而每个量级区域的合并总时间是O(n) (不管划分多少区域,总数量还是n),所以合并排序的时间复杂度是O(n*log₂n)
#include <iostream>
#include <stdlib.h>
using namespace std;
void merge(int num[],int p,int q,int r)
{
int n1 = q - p + 1;
int n2 = r - q + 1;
int left[n1+1], right[n2];
for(int i = 0; i < n1;++i)
left[i] = num[p + i];
left[n1] = 65536;
for(int j = 0; j < n2; ++j)
right[j] = num[q + j + 1];
right[n2-1] = 65536;
int i = 0,j = 0;
for(int x = p ; x <= r; x++ )
{
if (left[i] < right[j])
{
num[x] = left[i++];
}
else
{
num[x] = right[j++];
}
}
}
void mergeSort(int num[],int p,int r)
{
if(p < r)
{
int q = (p + r) / 2;
mergeSort(num, p, q);
mergeSort(num, q+1, r);
merge(num, p, q, r);
}
}
int main()
{
int max;
cin >> max;
int num[max];
for(int i = 0; i < max; i++)
{
num[i] = rand() % 100;
}
mergeSort(num,0,max-1);
for(int i = 0;i < max; i++)
{
printf("%d ",num[i]);
}
return 0;
}