世界上的排序算法千千萬,作為一名程式設計師 ,若僅對冒泡、插入、選擇或者是歸并、快排、堆排等主流排序方法背得滾瓜爛熟,未免讓排序算法這一斑斓的領域褪色。事實上,排序算法種類多樣到令人發指的程度。本文選出三種較有代表性的非主流排序方法略作介紹。
地精排序(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)
這次的主角變成了一隻猴子。本算法來源于科學家的一個笑話:讓一隻猴子坐在鍵盤前孜孜不倦地亂按,總會有一天,它連續打出的字母恰好是莎翁全集(且不說那時候猴子已經浪費了多少輩子做這些工作,鍵盤已被按壞了多少)……現在我們所說的程式猿先生們和這隻猴子多麼相像,同樣被“綁在”椅子上夜以繼日地打字…… 事實上,科學家研究表明猴子們往往對鍵盤上的某些特定的鍵更為好奇和喜愛~~ 暫且讓我們假設在這個算法中出現的猴子是理想猴子。給猴子一堆寫着數的卡片去排序,那麼這隻可憐的猴子會随意的将卡片抛向空中,張張卡片在空中劃出道道美妙的曲線。之後猴子将這些卡片拾起,滿懷希望地逐張檢查卡片是否被排成有序。随着希望的一次次破滅,卡片的一次次抛起,終會有一天,猴子能夠欣喜地發現卡片被排序成功了。 需要說的是,此算法最好時間複雜度為O(n),期望時間複雜度O(n*n!),最壞時間複雜度…… 猴子排序C++代碼實作:
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();
}
【本文原創,轉載請注明出處】http://blog.csdn.net/eolv99/article/details/39576819