希尔排序
这方法太恶心了,可以和冒泡、直插、选择进行组合,就是希尔排序里要内嵌其他排序,可是再希尔排序里实现其他排序,要进行一些脑筋急转弯的改变,所以刚学的时候肝了一天才弄明白;
大体说一说思路吧,以内嵌冒泡排序为例
加入这里有一个无序数字串:9876543210
我们要给他分组,一般会把总长除以二作为第一次的组数,102 = 5
所以我们把他分为如下图所示的两个一组共五组:

五组分别是(9 4)(8 3)(7 2)(6 1)(5 0)
对这五组分别进行冒泡排序
我们可以设置这样一个迭代来执行五次冒泡排序:
for(i = 1 , i < gap , i++)
{
/*
冒泡排序
*/
}
接下里,gap/2=2
又分为如下的两组:

这两组分别为(9 7 5 3 1)(8 6 4 2 0)
同样我们用上面的迭代,对两组分别做冒泡排序
因为分组后,每个子序列数据之间都隔着gap个距离,所以内嵌的排序要做出改动(以冒泡为例)
以在分为两组的情况下举例:
两个元素两个元素的比较,比如这一组第一个元素在数组中下标为j,那么这一组中第二个元素在数组中的下标为j+gap
冒泡排序结束时要保证这一组的元素是有序的,所以只有在对这一组元素进行冒泡排序时元素之间都不进行交换了就可以证明这组数有序了
就可以结束这一组的冒泡排序,进入下一组的冒泡排序
运行结果:

源码如下:
#include<stdio.h>
typedef int keytype;
//希尔排序
void shellsort(keytype k[] , int n)
{
int gap = n;
int j;
int flag = 1;
while (gap > 1)
{
gap = gap/2;
for (size_t i = 1; i <= gap; i++)//分为gap组,每组第一个元素为i
{
//子序列应用冒泡排序
do
{
flag=0;
for (j = i; j <= n-gap; j+=gap)
{
if (k[j] > k[j+gap])
{
k[0] = k[j];
k[j] = k[j+gap];
k[j+gap] = k[0];
flag = 1;
}
}
} while (flag==1);
}
}
}
#define MAX 100
int main()
{
//读取一串数字
printf("请输入一串无序数字:");
int c;
int n = 1;
keytype k[MAX];
while ((c = getchar())!='
')
{
k[n++] = c-'0';
}
if (c == '
')
{
k[n] = ' ';
}
//冒泡排序
shellsort(k,n-1);
printf("这串数字从小到大为:");
for (size_t i = 1; i <= n-1; i++)
{
printf("%d",k[i]);
}
return 0;
}