一、算法详解
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。一般情况下增量gap=length/2,缩小增量为gap=gap/2。
例:8 9 1 7 2 3 5 4 6 0 进行排序
1、gap=10/2=5,根据gap值对数组进行分组,则分组数等于gap的数值,所以分为五组,因为增量为5,所以每组的元素之间间隔为5,所以5组数为[8,3],[9,5],[1,4],[7,6],[2,0]。
2、对每组数进行直接插入排序,即将5组数均单独排序,调至有序状态,得到序列为3 5 1 6 0 8 9 4 7 2。
3、更新增量gap=5/2=2,对步骤二中得到的数列进行重新分组,即分为两组[3,1,0,9,7]和[5,6,8,4,2]。
4、对两组分别进行直接插入排序,得到新序列0 2 1 4 3 5 7 6 9 8。
5、更新增量gap=2/2=1,所以只有一个数组,即为4中得到的序列进行直接插入排序,得到排序后的序列0 1 2 3 4 5 6 7 8 9。
二、代码实现
void shell()
{
for(int gap=n/2;gap>0;gap/=2)//改变增量
{
for(int i=gap;i=0;j-=gap)
swap(a[j],a[j+gap]);
}
}
}
三、例题
沃老师并不会告诉大家分数的排名,但学生间竞争激烈,大家都想知道自己的作文成绩在班上的排名。Amy 8.999999999999999999999999999999999999999990000
Bob 8.9999999999999999999999999999999999999999800
Cat 8.9999999999999999999999999999999999999999899999999
输入共有N + 1行。 第一行有一个正整数N,代表班上有几个人。 接下来N行中的第i行,包含一个字符串namei,以及一个小数scorei,分别代表第i个人的名字以及第i个人的作文得分。
输出总共N行,每行由一个名字和一个小数构成,第i行代表着分数第i高的人的名字以及他的作文得分,代表作文得分的小数必须和输入一模一样,也就是原本末尾有多少零,输出也要有相同数量的零。 若分数相同,则名字字典序比较小的放在前面。
3 Amy 8.999999999999999999999999999999999999999990000 Bob 8.9999999999999999999999999999999999999999800 Cat 8.9999999999999999999999999999999999999999899999999
Amy 8.999999999999999999999999999999999999999990000 Cat 8.9999999999999999999999999999999999999999899999999 Bob 8.9999999999999999999999999999999999999999800
6 Aa1 3. Bb2 2. Cc3 1. a 5. A 5.0 9 5.00
9 5.00 A 5.0 a 5. Aa1 3. Bb2 2. Cc3 1.
请仔细观察这样例输入中的最后三行,虽然小数部分末尾0的数目不一样,但他们三个人都是同分的,所以必须按照名字字典序输出。
10 peter50216 5.0216 kelvin 9.9999999990 seanwu 9.999999999 pp5438 5.438 csferng1021 1.021 tmt514 5.140 dreamoon 0.00000000 shik 9.999999999 l521530 5.21530 coquelicot 9.999999999000000000
coquelicot 9.999999999000000000 kelvin 9.9999999990 seanwu 9.999999999 shik 9.999999999 pp5438 5.438 l521530 5.21530 tmt514 5.140 peter50216 5.0216 csferng1021 1.021 dreamoon 0.00000000
创建结构体,使用希尔排序对结构体进行排序,最后输出。
#include
#include
#include
#include
#include
#include
using namespace std;
//ios::sync_with_stdio(false);
typedef long long ll;
const int MAXN = 201000;
const int inf = 0x3f3f3f3f;
struct Student
{
string name;
string score;
}stu[MAXN];
int n;
bool cmp(Student a,Student b)
{
int lena = a.score.length();
int lenb = b.score.length();
while(a.score[lena-1]=='0') lena--;
while(b.score[lenb-1]=='0') lenb--;
if(a.score[0] > b.score[0]) return true;
if(a.score[0] < b.score[0]) return false;
int len = min(lena,lenb);
for(int i = 2;i < len;i ++)
{
if(a.score[i] > b.score[i]) return true;
else if(a.score[i] < b.score[i]) return false;
}
if(lena > lenb) return true;
else if(lenb > lena) return false;
return a.name < b.name ;
}
void shell()
{
int i, j, gap;
for (gap = n / 2; gap > 0; gap /= 2)
for (i = gap; i < n; i++)
for (j = i - gap; j >= 0 && cmp(stu[j],stu[j+gap]); j -= gap)
swap(stu[j], stu[j + gap]);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i = 0 ;i < n;i ++)
cin>>stu[i].name>>stu[i].score;
shell();
for(int i =n-1 ;i >=0;i --)
cout<