【算法雜談_01】那些非主流排序算法

世界上的排序算法千千萬,作爲一名程序設計師 ,若僅對冒泡、插入、選擇或者是歸併、快排、堆排等主流排序方法背得滾瓜爛熟,未免讓排序算法這一斑斕的領域褪色。事實上,排序算法種類多樣到令人髮指的程度。本文選出三種較有代表性的非主流排序方法略作介紹。


地精排序(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
發佈了25 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章