原理:每隔sp(整数)个数即取数并推断大小,交换,先构造局部有序序列。直到sp为1,构造完整的有序序列。
给出一组数据。例如以下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
49 | 38 | 65 | 97 | 76 | 13 | 27 | 49 | 55 | 4 |
对这个数据,将sp设为5,即先取49。与13比較,进行交换;再取38,与27对照,进行交换。以此内推。
终止条件是76与4对照完。至此,我们能够写出例如以下希尔函数的核心部分:
for(i=0;i<n-sp;i++)
for(j=i;j<n-sp;j+=sp)
if(a[j]>a[j+sp])
{
t=a[j];a[j]=a[j+sp];a[j+sp]=t;
}
当然,这不过走完了排序的第一趟!
要完毕真正的排序,还要进行循环!
一、C语言版
1、希尔函数
void ssort(int a[],int n,int sp) //n为数据大小,sp为间隔
{
int i,j,t;
for(i=0;i<n-sp;i++)
for(j=i;j<n-sp;j+=sp)
if(a[j]>a[j+sp])//假设前面你的大于后面的,则进行交换
{
t=a[j];a[j]=a[j+sp];a[j+sp]=t;
}
}
我们知道,希尔排序一趟是排不出终于结果的,sp要从大到小,最后取到1才干完毕,于是在主调函数里要调用多次ssort函数(如以下main函数里的标红部分),于是我们将多个sp综合到一个数组里。再将这个数组套入循环,就可以得到一个新的函数,这样在主函数里就能够直接调用该函数了,例如以下:
void shellsort(int a[],int n,int d[],int dn) //dn为sp的个数
{
int i;
for(i=0;i<dn;i++)
ssort(a,n,d[i]);
}
2、main函数
main()
{
inta[10]={49,38,65,97,76,13,27,49,55,4},j;
int d[]={5,3,1};
//ssort(a,10,5);
//ssort(a,10,3);
//ssort(a,10,1);
shellsort(a,10,d,3);//一次调用多个循环
for(j=0;j<10;j++)
printf("%d ",a[j]); //打印最后排序结果
printf("%d\n");
}
3. 结果显示
二、C#版
1. 构造算法类
class XiEr
{
public void ssort(int[] a, int n, int sp)
{
int i, j, t;
for (i = 0; i < n - sp; i++)
for (j = i; j < n - sp; j += sp)
if (a[j] > a[j + sp])
{
t = a[j]; a[j] = a[j + sp]; a[j + sp] = t;
}
}
public void shellsort(int[] a, int n, int[] d, int dn)
{
int i;
for (i = 0; i < dn; i++)
ssort(a, n, d[i]);
}
}
2. 前端调用
private void button1_Click(object sender, EventArgs e)
{
int j;
int[] a = { 49, 38, 100, 97, 76, 13, 27, 49, 55, 4 };
int[] d = { 5, 3, 1 };
XiEr xier = new XiEr();
xier.shellsort(a, 10, d, 3);
listBox1.Items.Clear();
string tt = "";
for (j = 0; j < 10; j++)
tt = tt + a[j].ToString() + '\t';
listBox1.Items.Add(tt);
}
3. 结果显示