#include
<
stdio.h
>
#include
<
stdlib.h
>
void
ShellSort(
int
a[],
int
Index);
void
PrintArray(
const
char
*
strMsg,
int
array[],
int
nLength);
int
main(
int
argc,
char
*
argv[])
{
int
data[
13
]
=
{
8
,
5
,
4
,
6
,
13
,
7
,
1
,
9
,
12
,
11
,
3
,
10
,
2
};
ShellSort(data,
13
);
//
PrintArray("Shell Sort:",data,13);
system(
"
PAUSE
"
);
return
0
;
}
/*
希尔排序的思路:
需要三层循环,
第一层循环用于控制步长的变化,步长每缩减一次就进行一轮排序;
第二层循环用于控制按照步长所分割成的各个集合;
第三层循环用于针对单个集合进行插入排序;
注:通过画图观察步长与小组个数的关系,可以知道,对于有13个元素的数组,
当步长为8时,可把数组分为8个小组,其中5组有2个元素,3组只有1个元素
当步长为7时,可把数组分为7个小组,其中1组有1个元素,6组有2个元素
当步长为6时,可把数组分为6个小组,其中1组有3个元素,5组有2个元素
当步长为5时,可把数组分为5个小组,其中3组有3个元素,2组有2个元素
当步长为4时,可把数组分为4个小组,其中1组有4个元素,3组有3个元素
*/
void
ShellSort(
int
a[],
int
Index) {
int
i, j, k;
//
循环计数变量
int
Temp;
//
暂存变量
int
Change;
//
数据是否改变
int
DataStep;
//
集合分割的步长
int
Pointer;
//
进行处理的位置
DataStep
=
(
int
) Index
/
2
;
//
初始集合间隔长度
while
(DataStep
!=
0
)
//
数列仍可进行分割
{
printf(
"
========================\n
"
);
//
对各个集合进行处理
/*(在j自增至DataStep的2倍之前,j代表各小组的第二个元素的位置;
j增至DataStep的3倍之前,j代表各小组的第三个元素的位置;依次类推。
若j-DataStep<0说明j已经是本小组的第一个元素了。)*/
for
(j
=
DataStep; j
<
Index; j
++
) {
Change
=
0
;
Temp
=
a[j];
//
保存当前集合的待排序元素到临时变量
//(推算本元素的前一个元素的位置)
Pointer
=
j
-
DataStep;
//
计算当前集合已排序元素列表的最后一个元素的位置
k
=
0
;
//
进行集合内数值的插入排序(边比较边向后移位)
while
(Temp
<
a[Pointer]
&&
Pointer
>=
0
&&
Pointer
<=
Index) {
printf(
"
当前交换元素:%d(a[%d])-%d(a[%d])\n
"
,a[Pointer],Pointer,a[Pointer
+
DataStep],Pointer
+
DataStep);
//
将比待排序元素大的已排序元素后移
a[Pointer
+
DataStep]
=
a[Pointer];
PrintArray(
"
本次交换结果:
"
,a,Index);
//
计算下一个要比较的已排序元素的位置
Pointer
=
Pointer
-
DataStep;
Change
=
1
;
k
++
;
}
printf(
"
本集合步长为%d,交换次数为%d\n
"
,DataStep,k);
//
(将待排序元素插入到最后的空位上)
a[Pointer
+
DataStep]
=
Temp;
if
(Change) {
//
打印目前排序结果
PrintArray(
"
本轮排序结果:
"
,a,Index);
}
printf(
"
------------------------\n
"
);
}
DataStep
=
DataStep
/
2
;
//
计算下次分割的间隔长度
}
}
void
PrintArray(
const
char
*
strMsg,
int
array[],
int
nLength)
{
int
i;
printf(
"
%s
"
,strMsg);
for
(i
=
0
;i
<
nLength;i
++
)
{
printf(
"
%d
"
,array[i]);
}
printf(
"
\n
"
);
}