竞赛训练2 排序:Insertion Sort
题目来源:《挑战程序设计竞赛》
题目: 编写一个程序,用插入排序将包含N个元素的数列A按升序排列。为检验算法的执行过程,请输入各计算步骤的数组(完成输入后的数组,以及每次i自增后的数组)。
输入:第一行输入定义数组长度的整数N。第二行输入N个整数,以空格隔开。
输出:输出共有N行。插入排序每个计算步骤中间结果各占用一行。数列的各元素之间空一格。请注意,行尾元素后的空格等多余的空格和换行会被认为是Presentation Error。
限制:1≤N≤100
输入示例
6
5 2 4 6 1 3
输出示例
5 2 4 6 1 3
2 5 4 6 1 3
2 4 5 6 1 3
2 4 5 6 1 3
1 2 4 5 6 3
1 2 3 4 5 6
由于之前数据结构课划水过于严重,所以本该信手拈来的题还需要调试半天……
思想很简单,整个排序过程将数组分为“已排序部分”和“未排序部分”两个阶段,一开始将第0个元素看成已排序的,后面的n-1个元素看成未排序的。插入排序需要注意的是两个循环变量和一个暂存当前值的变量的使用。
i | 指向未排序部分的开头元素,实际上就是从第1个元素一直向后遍历,直到第n-1个 |
---|---|
j | 从i-1一直向前遍历,直到发现有大于已排序部分当前值的就插入到该值后面,也就是赋值给j+1 |
v | 暂存a[i]的变量值 |
先贴一下自己写的,虽然没跑出来……
#include<iostream>
using namespace std;
#define MAX 1000
void Print(int a[],int n)
{
for(int i=0;i<n;++i)
{
cout<<a[i]<<" ";
}
}
int main()
{
int n,a[MAX],v;
cin>>n;
for(int i=0;i<n;++i)
{
cin>>a[i];
}
Print(a,n);
cout<<endl;
for(int i=1;i<n;++i)
{
v=a[i];
for(int j=i-1;j>=0;--j)
{
if(v<a[j])
{
a[j+1]=a[j];
}
a[j+1]=v;
}
Print(a,n);
cout<<endl;
}
return 0;
}
虽然没跑出来,但是思想是正确的(原谅我厚脸皮一波),主要问题是在于使用for循环来寻找插入位置,习惯了直接写int j,导致循环结束后无法找到插入位置(因为j的控制域已经失效了)。所以用for循环很难描述清楚这一过程,而用while循环会更加清楚和简洁。注意插入排序过程中while循环是从后往前逐个与v比较,并且逐个向后移。
#include<iostream>
using namespace std;
#define MAX 1000
void Print(int a[],int n)//打印函数
{
for(int i=0;i<n;++i)
{
cout<<a[i]<<" ";
}
}
int main()
{
int n,a[MAX],v,j;
cin>>n;
for(int i=0;i<n;++i)
{
cin>>a[i];
}
Print(a,n);
cout<<endl;
for(int i=1;i<n;++i)//插入排序
{
v=a[i];
j=i-1;
while(j>=0&&a[j]>v)
{
a[j+1]=a[j];
j--;
}
a[j+1]=v;
Print(a,n);
cout<<endl;
}
return 0;
}
结果是这样滴:
但是由于没有放在oj上测评,所以输出要求中对的空格和换行的要求无法表现出来,但是我自己写的压根没考虑这个问题……参考答案是在输出函数里实现的换行和空格的控制:
void trace(int a[],int n)
{
int i;
for(i=0;i<n;++i)
{
if(i>0) cout<<" "; //相邻元素之间输出1个空格
cout<<a[i];
}
cout<<endl;
}