Time limit: 10000MS Memory limit: 32768K
请用希尔排序对给定的数组进行从小到大排序后输出。
输入分两行,第一行一个整数n(1<=n<=3000000),第二行n个数,每个数都是32位整数型,两个数之间有1个空格隔开。
输出也分两行,第一行一个整数n,第二行是排序后的n个数,两个数之间有1个空格隔开。
Sample Input
5
5 4 3 2 1
Sample Output
5
1 2 3 4 5
用cin、cout会超时
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int const ic_limit = 3000002;
int iArr[ic_limit];
void vInput(int iN);
void vShellSort(int iN);
void vOutput(int iN);
int main()
{
int iN;
while(scanf("%d",&iN) != EOF)
{
memset(iArr,0,sizeof(iArr));
vInput(iN);
vShellSort(iN);
vOutput(iN);
}
return 0;
}
void vInput(int iN)
{
for(int i=1; i<=iN; i++)
{
scanf("%d",&iArr[i]);
}
}
void vOutput(int iN)
{
printf("%d\n",iN);
for(int i=1; i<iN; i++)
{
printf("%d ",iArr[i]);
}
printf("%d\n",iArr[iN]);
}
void vShellSort(int iN)
{
int i,j;
int iTemp;
int iDistance;
iDistance = iN/2;
while(iDistance >= 1)
{
for(i=iDistance; i<=iN; i++)
{
iTemp = iArr[i];
for(j=i; j>=iDistance && iTemp<iArr[j-iDistance]; j-=iDistance)
{
iArr[j] = iArr[j-iDistance];
}
iArr[j] = iTemp;
}
iDistance /= 2;
}
}
下面的解释是网上看到的:
希尔属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序
排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止
初始:d=5
49 38 65 97 76 13 27 49 55 04
49 13
|-------------------|
38 27
|-------------------|
65 49
|-------------------|
97 55
|-------------------|
76 04
|-------------------|
一趟结果:13 27 49 55 04 49 38 65 97 76
d=3
13 27 49 55 04 49 38 65 97 76
13 55 38 76
|------------|------------|------------|
27 04 65
|------------|------------|
49 49 97
|------------|------------|
二趟结果:13 04 49 38 27 49 55 65 97 76
d=1
13 04 49 38 27 49 55 65 97 76
|----|----|----|----|----|----|----|----|----|
三趟结果: 04 13 27 38 49 49 55 65 76 97
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。