编写自然归并合并排序算法
算法描述:对于初始给定的数组,通常存在多个长度大于1的已自然排好序的子数组段.例如,若数组a中元素为{4,8,3,7,1,5,6,2},则自然排好序的子数组段有{4,8},{3,7},{1,5,6},{2}.用一次对数组a的线性扫描就足以找出所有这些排好序的子数组段.然后将相邻的排好序的子数组段两两合并,构成更大的排好序的子数组段({3,4,7,8},{1,2,5,6}).继续合并相邻排好序的子数组段,直至整个数组已排好序。
1. 需求分析
1. 该程序编写与运行环境VC++6.0;
2. 输入的形式和输入值的范围:这是已经给定好的,无需再输入
3. 输出的形式:按从小到大的顺序依次输出一组整数,如:{1,2,3,4,5,6,7,8}
4. 程序所能达到的功能:对于初始给定的数组,通常存在多个长度大于1的已自然排好序的子数组段 ,然后将相邻的排好序的子数组段两两合并,构成更大的排好序的子数组段,继续合并相邻排好序的子数组段,直至整个数组已排好序。
3. 概要设计
1. 若要用程序实现以上功能,需要定义的数据结构(对数据的描述)有int类型和整型数组。
2. 本程序包含的函数有主函数main函数和子函数merge()、copy()、mergeSort ()函数;所用的循环有for循环;
4.详细设计
1. 主函数内数据定义与初始化:
int i; int c[8]={4,8,3,7,1,5,6,2};
2. main()的实现:
int main()
{
int i;
intc[8]={4,8,3,7,1,5,6,2};
mergeSort(c,0,7);
cout<<"{";
for(i=0;i<8;i++)
{cout<<c[i]<<",";}
cout<<"}";
return 0;
}
merge()函数的实现:
void merge(int a[],int b[],int left,int mn,int right)
{
int i=left;
int j=mn+1;
int k=left;
while(i<=mn&&j<=right)//i的取值范围为[left,mn],j的取值范围为[mn+1,right]
{
if(a[i]<a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
if(i>mn)//说明右边元素比左边元素多
{
int z;
for(z=j;z<=right;z++)
b[k++]=a[z];
}
else
{
int z;
for(z=i;z<=right;z++)
b[k++]=a[z];
}
}
mergeSort( ) 函数的实现:
void mergeSort(int a[], int left, int right)
{
int *b=new int[];
if(left<right) {//至少有2个元素
inti=(left+right)/2; //取中点
mergeSort(a, left, i);
mergeSort(a, i+1, right);
merge(a, b,left, i, right); //合并到数组b
copy(a, b,left, right); //复制回数组a
}
}
Copy()函数的实现:
void copy(int a[],int b[], int left,int right)
{
int i;
for(i=left;i<=right;i++)
a[i]=b[i];}
5.调试分析
main()的时间复杂度为O(n),空间复杂度为O(1):
int main()
{
int i;
intc[8]={4,8,3,7,1,5,6,2};
mergeSort(c,0,7);
cout<<"{";
for(i=0;i<8;i++)
{cout<<c[i]<<",";}
cout<<"}";
return 0;
}
merge()函数的时间复杂度为O(n),空间复杂度为O(n):
void merge(int a[],int b[],int left,int mn,int right)
{
int i=left;
int j=mn+1;
int k=left;
while(i<=mn&&j<=right)//i的取值范围为[left,mn],j的取值范围为[mn+1,right]
{
if(a[i]<a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
if(i>mn)//说明右边元素比左边元素多
{
int z;
for(z=j;z<=right;z++)
b[k++]=a[z];
}
else
{
int z;
for(z=i;z<=right;z++)
b[k++]=a[z];
}
}
mergeSort( ) 的时间复杂度为O(1),空间复杂度为O(1):
void mergeSort(int a[], int left, int right)
{
int *b=new int[];
if(left<right) {//至少有2个元素
inti=(left+right)/2; //取中点
mergeSort(a, left, i);
mergeSort(a, i+1, right);
merge(a, b,left, i, right); //合并到数组b
copy(a, b,left, right); //复制回数组a
}
}
Copy()的时间复杂度为O(n),空间复杂度为O(n):
void copy(int a[],int b[], int left,int right)
{
int i;
for(i=left;i<=right;i++)
a[i]=b[i]}
该程序调试采用单步跟踪法,首先先初始化数据,然后开始进入merge()函数,
然后单步跟踪mergeSort(),在单步跟踪copy(),遇到main()函数cout调试结束;
6.使用说明
#include<iostream.h>
void merge(int a[],int b[],int left,intmn,int right)
{
inti=left;int j=mn+1; int k=left;
while(i<=mn&&j<=right)//i的取值范围为[left,mn],j的取值范围为[mn+1,right]
{
if(a[i]<a[j])b[k++]=a[i++];
elseb[k++]=a[j++]; }
if(i>mn)//说明右边元素比左边元素多
{ intz; for(z=j;z<=right;z++) b[k++]=a[z]; }
else{intz; for(z=i;z<=right;z++) b[k++]=a[z]; }}
void copy(int a[],int b[], int left,int right)
{
int i;
for(i=left;i<=right;i++)
a[i]=b[i];
}
void mergeSort(int a[], int left, int right)
{
int*b=new int[];
if (left<right) {//至少有2个元素
int i=(left+right)/2; //取中点
mergeSort(a, left, i);
mergeSort(a, i+1, right);
merge(a, b, left, i, right); //合并到数组b
copy(a, b, left, right); //复制回数组a
}
}
int main()
{
int i;
intc[8]={4,8,3,7,1,5,6,2};
mergeSort(c,0,7);
cout<<"{";
for(i=0;i<8;i++)
{cout<<c[i]<<",";}
cout<<"}";
return0;
}
基本思想:将待排序元素分成大小大致相同的2个子集合,分别对两个字集合排序,最终将排好的子集合合并成为所要求的排好序的集合;
以上程序在VC++6.0环境下编写与运行的,该程序采用c++编程,执行该程序时,无需输入,主函数的的数据类型和初始化之后,调用merge()函数,转到merge()函数之后,merge函数递归调用它本身,再调用mergeSort()函数和copy()函数,最后输出;
7.测试结果