經典排序演算法---希爾排序(C/C#)
原理:每隔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. 結果顯示