一.直接插入排序
在希爾排序之前,我們先來看一下比較簡單的直接插入排序。其算法思想主要是,將一個無序的數據插入到已經排好序的有序表中,從而得到一個數據量+1的有序表。以此類推,便可將所有數據變爲有序。
這種思想在生活中十分常見,比如你有一堆無序的作業,你會看一下第二份作業的序號,然後與第一份作業的序號相比,如果大於,則第二份放在最上面,否則位置不動。在這個過程中,第一份作業就是一個有序表(一個數據必定有序),然後操作完成後,你便得到了有2個數據的有序表。接下來,第3個,第4個.....直到全部有序。
時間複雜度:O(n^2),需要一個數據的輔助空間。
代碼:
for(int i=2;i<max;i++)//直接插入排序,從第二個數據開始
{ //data數組從data[1]開始存放數據
int j;
data[0]=data[i];//data[0]用來暫存要插入的數據
for(j=1;j<i;j++)//找到要插入的位置
if(data[i]<data[j]) break;
if(j>=i) continue;//無需插入
for(int k=i-1;k>=j;k--)
data[k+1]=data[k];//後移
data[j]=data[0];//插入
}
二.希爾排序
希爾排序又稱“縮小增量排序”,時間效率會高很多。話不多說,先看代碼。
void InsertSort(int data[])//希爾排序
{
printf("希爾排序:\n");
//生成隨機數並輸出
for(int i=1;i<max;i++)
data[i]=rand()%100;
for(int i=1;i<max;i++)
printf("%3d",data[i]);
int i,j,d;
d=(max-1)/2;//折半取d
while(d>=1)
{
for(i=1;i<max-d;i++)//或者i=d+1;i<max;i++,那後面的j也要相應的變爲,j=i-d;
{
j=i;
while(j>0)
{
if(data[j+d]<data[j])//如果後面的小,則交換
{
data[0]=data[j];
data[j]=data[j+d];
data[j+d]=data[0];
j=j-d;//繼續往前比較
}
else j=0;//如果後面的較大,說明已經有序,直接退出while循環
}
}
printf("\n增量爲%d的排序結果:\n",d);
for(int i=1;i<max;i++)
printf("%3d",data[i]);
d=d/2;
}
}
剛開始是生成隨機數,就不用多說了。然後取增量d,增量的取法多種多樣,不同的取法適合不同類型的問題,我們這裏採用比較常見的折半取增量,d最後一次一定爲1(最後一次直接插入排序一趟)。其他的看註釋也就差不多了,本質上還是插入排序,只不過是隔幾個數據排序。
三.其他插入排序
其他的插入排序方法也有很多,都不怎麼常用,如:2路,表插等,有時間再寫寫吧。
ps:希爾排序的時間複雜度不一定是n^2,要看增量取法。