代碼
#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");
}