如果你覺得我的有些話有點唐突,你不理解可以想看看前一篇《C++之冒泡排序、希爾排序、快速排序、插入排序、堆排序、基數排序性能對比分析》。
這幾天閑着沒事就寫了一篇《C++之冒泡排序、希爾排序、快速排序、插入排序、堆排序、基數排序性能對比分析》的隨筆,由於當時有點腦殘把希爾排序寫錯了,導致其性能很多情況下都查過了快速排序。當時我就懷疑我的算法的正確性了,由於當時的激動沒來得及檢查,我直呼不可思議,以至於讓快速排序任希爾排序做了老爺O(∩_∩)O哈哈~,這晚輩太不敬了。感謝博友“墮落的惡魔”給我指了出來,同時和各位博友交流的過程也讓我長見識了。正確的快速排序我已經更改過來了,大家不要受我之前的誤導。現在重新測試一遍。
排序算法時間復雜度和空間復雜度對比:
注意:基數排序中的d是最大數的次數,r是桶數。
再和博友討論之后,做了一些改進。
1、改進Swap()算法為:
1 inline void Swap(int &a,int &b) 2 { 3
4 a=a^b; 5 b=a^b; 6 a=a^b; 7 }
這里看上去似乎很完美,多簡潔明了啊!!可是當我打印出結果一看我和我的小伙伴都驚呆了!!!!!如下圖:
待排序數為:int a[20]={25,19,6,58,34,10,7,98,160,0,345,445,675,34,7,122,8,435,23,678};
可結果如下圖:
分析發現:如果Swap(a,a)就會把a置零,而如果a=3,b=3,Swap(a,b)則不影響。尼瑪,這么多陷阱!然后改代碼如下:
1 inline void Swap(int &a,int &b) 2 { 3 if(a!=b) 4 { 5 a=a^b; 6 b=a^b; 7 a=a^b; 8 } 9 }
現在對比改進前和改進后的效率對比用快速排序測試1千萬個數據。
改進前:
改進后:
總結:實踐發現效率並沒有升高,反而降低了。看來這種改進並沒有什么直接的作用,當然這里有一個影響的因素是兩組測試的數據只是個數相等。具體值都是用程序生成的隨機數。
2、改進快速排序:
主要改進了基准值的選取是隨機的。
改進代碼:
1 //快速排序
2 /////////////////////////////////////// 3 inline void Swap(int &a,int &b) 4 { 5 int temp; 6 temp=a; 7 a=b; 8 b=temp; 9 // if(a!=b) 10 // { 11 // a=a^b; 12 // b=a^b; 13 // a=a^b; 14 // }
15 } 16
17 int Partition(int a[],int p,int r) 18 { 19 int i=p; 20 int j=r+1; 21 int x=a[p]; 22 while (true) 23 { 24 while(a[++i]<x&&i<r); 25 while(a[--j]>x); 26 if (i>=j)break; 27 Swap(a[j],a[i]); 28
29 } 30 a[p]=a[j]; 31 a[j]=x; 32 return j; 33 } 34 inline int Random(int p,int r) 35 { 36 return (p+(rand()%(r-p+1)));//p=<x<=r
37 } 38
39 int RandomPartition(int a[],int p,int r ) 40 { 41 int i=Random(p,r); 42 Swap(a[i],a[p]); 43 return Partition(a,p,r); 44 } 45
46 void QuickSort(int a[],int p,int r) 47 { 48 if (p<r) 49 { 50 int q=RandomPartition(a,p,r); 51 QuickSort(a,p,q-1); 52 QuickSort(a,q+1,r); 53 } 54 }
改進前:
改進后:
小結:尼瑪,這神馬情況。這效率越改越低,哪位大俠有更好的改進方法可以交流一下。
3、接下來我重測一下排序英雄榜(昨天測的大家就當看笑話了O(∩_∩)O)
今天博友 Sam Xiao提供一種前所未見的排序算法(我稱之為SomeoneSort算法),其效率之低讓人嘆為觀止(感覺時間復雜度接近O(n!))!當然這里並沒有嘲笑的意思,多一種方法,多一種思路學習一下都是不錯的。拿出來和大家分享一下:
1 //從未見過效率如此低的排序算法
2 void SomeoneSort(int a[],int n) 3 { 4 //int count=0;
5 int i=0; 6 while (i<n-1) 7 { 8 if(a[i]>a[i+1]) 9 { 10 Swap(a[i],a[i+1]); 11 i=0; 12 //count++;
13 continue; 14 } 15 i++; 16 } 17 //cout<<count<<"次"<<endl;
18 }
下面拿SomeOneSort和BulbleSort對比一下:
下面重新測一下昨天7個排序算法,具體改過的只有快速排序和希爾排序:
數據量1:
數據量10:
數據量100:
數據量1000:
數據量10000:
數據量50000:
數據量100000:
數據量200000:
數據量300000:
數據量1百萬:
數據量1千萬:
數據量1億:
數據量5億:
數據量5億:
數據量5.2億:
總結:昨天和今天兩天啥事沒干就是在測試這些算法,收獲很多。首先算法的好壞不能一概而論,得看具體情況。具體情況就是指待排的數據量,和你能承受的內存空間。比如基數排序在數據量在1w~20w之間 高於快速排序,但是這是需要空間作為代價的。30w后基數排序就掛,當然這可能和我的編碼有關。但是從總體性能來說,應該是滿足這一規律的,快速排序一路測下來確實表現的很好,但是在代碼的健壯性方面可能不及希爾排序,就效率將希爾排序和快速排序是一個數量級上的當然我得承認這些排序代碼我並沒有真正用於實際的項目中,往往只是對付筆試和面試。本人小本科一枚,最近忙着找工作,所以遇到了就在復習復習。真正用於項目中肯定還有許多需要優化和改進的地方。或者是組合多種排序算法,使之成為一個更復雜效率更高的算法。讀書讀到現在大家應該知道,生活中、學習中、工作中、以至於我們搞算法、計算機安全領域。最好的接解決方案無非是根據實際情況各種因素的權衡,把手中的的多套方案進行妥協和折中,找一個最佳的平衡點。
很快自己也要走進社會了,就像剛剛進入大學前的一段時間,心中滿是憧憬和期待,即便別人說社會是怎樣怎樣的復雜和現實。有的時候甚至會在想工作的第一個月的工資要干什么?好期待第一月的工資,其實我已經計划好了,O(∩_∩)O哈哈~。回顧大學的這將近四年。讓我改變最大的還是我的思想,我覺得這也是最寶貴的,有為人處世方面的,也有學習方法方面的,至少現在我的自學能力比以前提高了不知道多少!基本上遇到的技術問題在互聯網和圖書管總能找到或多或少都能找到答案,當然我們要珍惜老師上課的時光,我覺得那是學習知識最快的方式。這一個多月來我學習的積極性是如此的高,從未有過!我的舍友們也是,我們老是開玩笑說“要是大一就有現在的思想我早就怎么怎么了……”,如果你還不用面臨畢業,那么以半個過來人的身份告訴你“好好地學習,好好學習一門你感興趣的技術,如果你不確定你對什么感興趣你可以找一個你不至於討厭的先學一學,慢慢發現你是否喜歡這個”根據我的經驗你有足夠時間嘗試這樣三次左右,當然這后最好找一個你感興趣的領域好好的學習。切記不可三天打魚兩曬網,因為如果你手中掌握一門技能對你以后找工作是有很大好處的。作為一名很菜的“程序猿”,我必須明白與時俱進的學習新知識才能不斷提高我的生產力。也才有能力養活自己,養活自己的家庭以及以后年邁的父母。大家一起加油!!!(很明顯跑題了!!O(∩_∩)O哈哈~)
有不妥的地方歡迎大家指正!!共同學習!!
最后聲明一點:快速排序還是希爾排序他爹!!
推薦一段博友分享的排序視頻很藝術、很形象、很生動哦(http://www.oschina.net/question/561584_65522)