在數據結構中講解了7中排序算法,冒泡、選擇、插入、希爾、堆排序、歸併、快速排序。希爾排序感覺有點神,還沒搞明白,以後再說。
本篇講述冒泡、選擇、插入這3種時間複雜度O(n^2)的算法
冒泡排序
冒泡排序非常簡單,但是如果正常寫的話還是有優化的餘地的,一般我們寫的代碼爲:
void BubbleSort_1(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
for (i=low;i<=high-1;i++)
{
for (j=i+1;j<=high;j++)
{
if (a[i]>a[j])
swap(&a[i],&a[j]);
}
}
}
但是這種方法後面部分(i後面的數組)的數值順序是不變的,如果按照正宗的“冒泡”來的話,每一次 i 循環後,較小的數都會相應的向前靠攏,代碼修改爲:
void BubbleSort_2(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
for (i=low;i<=high-1;i++)
{
for (j=high-1;j>=i;j--)
{
if (a[j]>a[j+1])
swap(&a[j],&a[j+1]);
}
}
}
還有一種,如果某次循環後數組後面已經是順序的話,那就不需要在進行排序了,加入一個標誌位即可:
void BubbleSort_3(double *a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
bool sign=true;
for (i=low ; i<=high-1&&sign ; i++)
{
sign=false;
for (j=j=high-1 ; j>=i ; j--)
{
if (a[j]>a[j+1])
{
swap(&a[j],&a[j+1]);
sign=true;
}
}
}
}
選擇排序
這個就比較簡單了,從首位開始,每次都選擇當前位和後面數組中最小的來交換當前位。
void SelectSort(double* a,int low,int high)
{
if (!a||high<low)
return;
int i,j,min;
for (i=low;i<=high;i++)
{
min=i;
for (j=i+1;j<=high;j++)
{
if (a[j]<a[min])
min=j;
}
swap(&a[i],&a[min]);
}
}
插入排序
插入排序的算法也很簡單,就是假設當前位之前的數組已經排序好,然後把當前位插入到前面數組的合適位置,具體做法爲依次比較,直到找到比當前位小的值。
void InsertSort(double* a,int low,int high)
{
if (!a||high<low)
return;
int i,j;
double key;
for (i=low ; i<high ; i++)
{
j=i;
key=a[i+1];
while (a[j]>key&&j>=low)
{
a[j+1]=a[j];
j--;
}
a[j+1]=key;
}
}
可以粗略估計下這3個排序的優劣,冒泡和選擇排序的比較次數都是相同的,都是O(n^2),但是選擇排序的交換操作比冒泡少,所以選擇要比冒泡強。而插入排序在最壞情況下的比較次數和選擇排序是一樣的,但是如果數組已經基本有序的話,那麼內循環的執行次數是比較少的,
所以平均情況下,插入排序 優於 選擇排序
優於 冒泡排序
現在我們來測試下這3種方法的時間,測試數組大小爲5萬,裏面的值是隨機生成的浮點值。(結果冒泡中第一種時間最短,好糾結啊)