8645 归并排序(非递归算法)
时间限制:1000MS 代码长度限制:10KB
提交次数:2398 通过次数:1192
题型: 编程题 语言: G++;GCC
Description
用函数实现归并排序(非递归算法),并输出每趟排序的结果
输入格式
第一行:键盘输入待排序关键的个数n 第二行:输入n个待排序关键字,用空格分隔数据
输出格式
每行输出每趟排序的结果,数据之间用一个空格分隔
输入样例
10 5 4 8 0 9 3 2 6 7 1
输出样例
4 5 0 8 3 9 2 6 1 7 0 4 5 8 2 3 6 9 1 7 0 2 3 4 5 6 8 9 1 7 0 1 2 3 4 5 6 7 8 9
思路:和递归的归并排序相反,在循环次数f内(最大数据量high确定),使相邻的2^i(i=1,2,3,...每次循环+1)个数据块排序,在最后一次排序就是(1,high),排序完成。
循环次数的计算:
3个数据,每次进行排序的数据块,如下
(1,2) | (3,3) |
(1,3) |
6个数据,每次进行排序的数据块,如下
(1,2) | (3,4) | (5,6) |
(1,4) | (5,6) | |
(1,6) |
10个数据,每次进行排序的数据块,如下
(1,2) | (3,4) | (5,6) | (7,8) | (9,10) |
(1,4) | (5,8) | (9,10) | ||
(1,8) | (9,10) | |||
(1,10) |
……
往下写可以发现有:
第一行是数据量high,第二行是循环次数f
3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 16 |
2 | 2 | 3 | 3 | 3 | 3 | 4 | 4 | 4 |
可以看出是log2(high)向上取整的关系
int edge(int high) //计算循环次数
{
double h=log2(high);
high = log2(high);
if(high==h) //向上取整
return high;
else if(high<h)
return high+1;
}
代码实现:
- 合并两个有序表
测试学习使用:
void Merger(int *a,int *b,int low,int mid,int high)
{
//printf("此次low:%d,mid:%d,high:%d\n",low,mid,high);
if(low==high) {
b[low] = a[low];
return;
}
int l=low,j=mid+1,r=high,k=low;
while(l<=mid && j<=high)
{
if(a[l]>a[j] && j<=r)
b[k++] = a[j++];
else if(a[l]<a[j] && l<=mid)
b[k++] = a[l++];
else if(a[l]==a[j])
b[k++] = a[l++];
//printf("经过一次循环low:%d,mid:%d,high:%d\nb数组为:",low,mid,high);
//print(b,high);
}
while(l<=mid) b[k++] = a[l++];
while(j<=high) b[k++] = a[j++];
//printf("最终low:%d,mid:%d,high:%d\nb数组为:",low,mid,high);
//print(b,high);
for(int i=low; i<=high; i++)
a[i] = b[i];
//printf("a数组为:");
//print(a,high);
}
代码段:
void Merger(int *a,int *b,int low,int mid,int high)
{
if(low==high) //只有一个比较的时候直接赋值到b数组
{
b[low] = a[low];
return;
}
int l=low,j=mid+1,r=high,k=low;
while(l<=mid && j<=high)
{
if(a[l]>a[j] && j<=r)
b[k++] = a[j++];
else if(a[l]<a[j] && l<=mid)
b[k++] = a[l++];
else if(a[l]==a[j])
b[k++] = a[l++];
}
while(l<=mid) b[k++] = a[l++];
while(j<=high) b[k++] = a[j++];
for(int i=low; i<=high; i++) //赋值到b数组
a[i] = b[i];
}
2.找数据块
void m_sort(int *a,int *b,int low,int high,int n)
{
if(low>=high)
return;
int f = edge(high),s,S,z,s0;
for(int i=1; i<=f; i++)
{
for(s=1,S=pow(2,i);; s=S+1,S=S+i*2)
{
if(s>high)
break;
if(S>high)
{
if(i==f&&z!=0)
{
S = high;
//printf("s:%d s0:%d S:%d i:%d\n",s,s0,S,i);
//printf("排序前是:");
//print(b,S);
Merger(a,b,s,s0,S);
//printf("排序后是:");
//print(b,S);
break;
}
z=0;
S = high;
//printf("s:%d S:%d i:%d\n",s,S,i);
//printf("排序前是:");
//print(b,S);
Merger(a,b,s,(s+S)/2,S);
//printf("排序后是:");
//print(b,S);
s0 = s-1;
z++;
break;
}
//printf("s:%d S:%d i:%d\n",s,S,i);
//printf("排序前是:");
//print(b,S);
Merger(a,b,s,(s+S)/2,S);
//printf("排序后是:");
//print(b,S);
}
print(b,n);
}
}
void m_sort(int *a,int *b,int low,int high,int n)
{
if(low>=high)
return;
int f = edge(high),s,S,z,s0;
for(int i=1; i<=f; i++)
{
for(s=1,S=pow(2,i);; s=S+1,S=S+i*2)
{
if(s>high)
break;
if(S>high)
{
if(i==f&&z!=0)
{
S = high;
Merger(a,b,s,s0,S);
break;
}
z=0;
S = high;
Merger(a,b,s,(s+S)/2,S);
s0 = s-1;
z++;
break;
}
Merger(a,b,s,(s+S)/2,S);
}
print(b,n);
}
}