归并排序
基本思想:将数组看到n个长度为1有序表,将相邻的k个有序子表成对归并,得到一个新的有序子表。反复操作,最后得到一个长度为n的有序表。
k=2时,就是二路归并排序。
分治法
1 自底向上的二路归并
策略:分解(原序列看成为n个长度为1的子序列)->求解子问题(相邻子序列合并)->合并(整个序列在数组a中,此处可以忽略)
其中,“相邻子序列合并”时,先将原序列a[]中的两个子表,进行逐个比较,较小者放到一个临时表tmp[],得到一个临时有序表,再将其复制到原序列a中。
#include<bits/stdc++.h>
using namespace std;
//输出数组中的所有元素
void disput(int a[], int n)
{
for(int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
//合并两个相邻序列
void Merge(int a[], int low, int mid, int high)
{
int *tmpa; //一个临时数组
tmpa=(int*)malloc((high-low+1)*sizeof(int));
int i=low, j=mid+1, k=0;
while(i<=mid&&j<=high) //两个数组均为扫完
{
if(a[i]<=a[j])
{
tmpa[k]=a[i];
i++;
k++;
}
else
{
tmpa[k]=a[j];
j++;
k++;
}
}
while(i<=mid)
{
tmpa[k]=a[i];
i++;
k++;
}
while(j<=high)
{
tmpa[k]=a[j];
j++;
k++;
}
for(k=0, i=low; i<=high; k++, i++) //还原
a[i]=tmpa[k];
free(tmpa);
}
// 一趟二路归并
void MergePass(int a[], int length, int n)
{
int i;
for(i=0; i+2*length-1<n; i=i+2*length)
Merge(a, i, i+length-1, i+2*length-1);
if(i+length-1<n) //归并剩下的子表
Merge(a, i, i+length-1, n-1);
}
// 二路归并算法
void MergeSort(int a[], int n)
{
int length;
for(length=1; length<n; length=2*length)
MergePass(a, length, n);
}
int main()
{
int n=5;
int a[n]={2, 33, 45, 16, 8};
cout<<"原序列为:"<<endl;
disput(a, n);
MergeSort(a, n);
cout<<"二路归并排序后:"<<endl;
disput(a, n);
return 0;
}
时间复杂度:O(nlog(2)(n))。
2 自顶向下的二路归并
策略:分解(原序列一分二)->求解子问题(两个子序列二路归并并排序,知道子序列长度为0/1)->合并(合并已排序的两个子序列)
#include<bits/stdc++.h>
using namespace std;
//输出数组中的所有元素
void disput(int a[], int n)
{
for(int i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
//合并两个相邻序列
void Merge(int a[], int low, int mid, int high)
{
int *tmpa; //一个临时数组
tmpa=(int*)malloc((high-low+1)*sizeof(int));
int i=low, j=mid+1, k=0;
while(i<=mid&&j<=high) //两个数组均为扫完
{
if(a[i]<=a[j])
{
tmpa[k]=a[i];
i++;
k++;
}
else
{
tmpa[k]=a[j];
j++;
k++;
}
}
while(i<=mid)
{
tmpa[k]=a[i];
i++;
k++;
}
while(j<=high)
{
tmpa[k]=a[j];
j++;
k++;
}
for(k=0, i=low; i<=high; k++, i++) //还原
a[i]=tmpa[k];
free(tmpa);
}
// 二路归并算法
void MergeSort(int a[], int low, int high)
{
int mid;
if(low<high)
{
mid=(low+high)/2;
MergeSort(a, low, mid);
MergeSort(a, mid+1, high);
Merge(a, low, mid, high);
}
}
int main()
{
int n=5;
int a[n]={2, 33, 45, 16, 8};
cout<<"原序列为:"<<endl;
disput(a, n);
MergeSort(a, 0, n-1);
cout<<"二路归并排序后:"<<endl;
disput(a, n);
return 0;
}