世界上的排序算法千千萬,作爲一名程序設計師 ,若僅對冒泡、插入、選擇或者是歸併、快排、堆排等主流排序方法背得滾瓜爛熟,未免讓排序算法這一斑斕的領域褪色。事實上,排序算法種類多樣到令人髮指的程度。本文選出三種較有代表性的非主流排序方法略作介紹。
地精排序(Gnome Sort)
傳說中最簡單的排序算法。從前在一個美麗的大花園中,有一隻地精在打零工,工作簡單至極——將一排花盆排序。這隻小傢伙便從第一個花盆開始向後走,每遇到一個更小的花盆,就會將它“拖拽”到應處的位置。終於,地精走到了最後一個花盆處,成功地完成了它的工作。
代碼只需要一重循環,但最壞時間複雜度爲O(n^2)。不過在原先的花盆較爲有序時,地精拖拽花盆的總距離會減少,時間複雜度可達到接近O(n)的程度。綜合來看,其時間複雜度和插入排序基本相當。
地精排序C++代碼實現:
void Gnome_Sort()
{
int i=1;
while(i<=n)
i>1&&a[i-1]>a[i]?swap(a[i-1],a[i]),i--:i++;
}
臭皮匠排序(Stooge Sort)
一個遞歸排序算法。它的提出者稱其爲“一種漂亮的排序算法”,但顯然大家並不這樣認爲,反而在這種算法原理上產生了不好的聯想——這個算法由此得名。
其實這種排序算法雖然又慢又不實用,但它的思想的確是“極好的”。
有三個臭皮匠,而整個序列被他們等分成了三份,每一次排序第二個臭皮匠都會先威脅第一個臭皮匠交出所有的大數,並將較小的數強塞到他的手中(遞歸排序區間內前2/3的數)。之後第三個臭皮匠又對第二個臭皮匠做了同樣的事情(再遞歸排序後2/3的數)。那麼整個序列中的大數都到了第三個臭皮匠的手中。而第二個臭皮匠豈能善罷甘休,又將第一個臭皮匠痛扁了一頓,得到了剩餘的較大的數(重複第一次排序)。而第一個臭皮匠只能拿着一堆小數感慨自己生不逢時……
注:在整個過程中,三個臭皮匠手中的數的數目不變。
在實際代碼實現上,排序的最開始階段我們需要判斷如果這段區間的第一個數大於最後一個數,先將其互換位置,再進行三段排序。
總時間複雜度O(n^2.7)。
臭皮匠排序C++代碼實現:
inline void Stooge_Sort(int l,int r)
{
if(a[r]<a[l])
swap(a[l],a[r]);
if(r-l+1>=3)
{
int t=(r-l+1)/3;
Stooge_Sort(l,r-t);
Stooge_Sort(l+t,r);
Stooge_Sort(l,r-t);
}
}
猴子排序(Bogo Sort)
inline void Shuffle()
{
for(int randnum,i=1;i<=n;i++)
randnum=rand()%(n-i+1),
swap(a[i],a[i+randnum]);
}
inline bool Check()
{
for(int i=2;i<=n;i++)
if(a[i]<a[i-1])
return false;
return true;
}
void Bogo_Sort()
{
while(!Check())
Shuffle();
}