1. 程式人生 > >c語言實現希爾排序

c語言實現希爾排序

自己看書時,對希爾排序的理解一直處於茫然狀態,然後在維基百科上看到了這樣一句話,再加上這樣一個例子,總算消除了我的迷惑。

因為訪問危機百科需要翻牆,故複製了了相關內容在本部落格裡,若讀者已翻牆,可以直接點此進入維基百科檢視。

--------------------------------------以下內容來源於維基百科--------------------------------------

一個更好理解的希爾排序實現:將陣列列在一個表中並對列排序(用插入排序)。重複這過程,不過每次用更長的列來進行。最後整個表就只有一列了。將陣列轉換至表是為了更好地理解這演算法,演算法本身僅僅對原陣列進行排序(通過增加索引的步長,例如是用

i += step_size而不是i++)。

例如,假設有這樣一組數[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我們以步長為5開始進行排序,我們可以通過將這列表放在有5列的表中來更好地描述演算法,這樣他們就應該看起來是這樣:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

然後我們對每列進行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

將上述四行數字,依序接在一起時我們得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].這時10已經移至正確位置了,然後再以3為步長進行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

排序之後變為:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最後以1步長進行排序(此時就是簡單的插入排序了)。

--------------------------------------以上內容來源於維基百科--------------------------------------

值得注意的是,在希爾排序裡,注意選擇增量因子,最後一個增量因子必須是1,其次各增量之間不應該含有公約數,或者說各個增量互素。

下面是我的實現程式碼,其中考慮了增量排序的問題,避免輸入有誤。這個程式碼是為了學習插入排序而寫的,本來增量因子排序那個直接插入排序函式是可以省的,我還是寫上了。便於與希爾排序做個比較。

#include<stdio.h>

#define MaxSize 100

struct DataType
{
	int data;
};

struct Sqlist
{
	DataType R[MaxSize];
	int length;
};

//直接插入排序對增量因子由大到小排序
void DirectSort(int *da,int n)
{
	int i,j;
	int temp;
	for(i=1;i<n;i++)
	{
		if(da[i-1] < da[i])
		{
			temp = da[i];//設定temp為哨點
			j=i-1;
			
			while(da[j] < temp)
			{
				da[j+1] = da[j];
				j--;
				if(j<0)
				{
					break;
				}
			}
			da[j+1] = temp;
		}
	}
}

void ShellInsert(Sqlist *l,int d)
{
	//對R陣列進行希爾排序,d為增長因子
	int i,j;
	for(i=d+1;i<=l->length;i++)
	{
		if(l->R[i].data > l->R[i-d].data)
		{
			//向前尋找插入位置
			l->R[0] = l->R[i];//置哨點

			j = i-d;
			while(l->R[0].data > l->R[j].data)
			{
				l->R[j+d] = l->R[j];
				j=j-d;

				if(j<0)
				{
					break;
				}
			}
			l->R[j+d] = l->R[0];
		}
	}
}

//希爾排序
void ShellSort(Sqlist *l)
{
	//按遞增序列對順序表R陣列做希爾排序
	int d[10],t,k;
	printf("\n輸入增量因子的個數:");
	scanf("%d",&t);
	printf("由大到小輸入每一個增量因子:\n");
	for(k=0;k<t;k++)
	{
		scanf("%d",&d[k]);
	}

	//對增量因子進行排序,以防出錯
	DirectSort(d,t);

	for(k=0;k<t;k++)
	{
		printf("%d ",d[k]);
	}

	printf("\n");

	for(k=0;k<t;k++)
	{
		ShellInsert(l,d[k]);
	}
}

int main()
{
	Sqlist list;
	list.length = 10;

	int data[10] = {2,6,1,4,9,6,8,7,3,9};

	//初始化資料
	for(int i=0;i<list.length;i++)
	{
		list.R[i+1].data = data[i];
	}

	ShellSort(&list);

	for(int i=0;i<list.length;i++)
	{
		printf("%d ",list.R[i+1].data);
	}

}

執行截圖: