詳細解說 STL 排序 Sort (三)

2021-05-25 17:32:02 字數 3520 閱讀 5988

1.6 nth_element 指定元素排序

nth_element乙個容易看懂但解釋比較麻煩的排序。用例子說會更方便:

班上有10個學生,我想知道分數排在倒數第4名的學生。

如果要滿足上述需求,可以用sort排好序,然後取第4位(因為是由小到大排), 更聰明的朋友會用partial_sort, 只排前4位,然後得到第4位。其實這是你還是浪費,因為前兩位你根本沒有必要排序,此時,你就需要nth_element:

template

<

class randomaccessiterator>

void nth_element(randomaccessiterator first, randomaccessiterator nth, randomaccessiterator last);

template

<

class randomaccessiterator,

class strictweakordering>

void nth_element(randomaccessiterator first, randomaccessiterator nth, randomaccessiterator last, strictweakordering comp);

對於上述例項需求,你只需要按下面要求修改1.4中的程式:

stable_sort(vect.begin(), vect.end(),less());

替換為:

nth_element(vect.begin(), vect.begin()+3, vect.end(),less());

執行結果為:

------before sort... tom: 74 jimy: 56 mary: 92 jessy: 85 jone: 56 bush: 52 winter: 77 andyer: 63 lily: 76 maryia: 89 -----after sort .... jone: 56 bush: 52 jimy: 56 andyer: 63 jessy: 85 mary: 92 winter: 77 tom: 74 lily: 76 maryia: 89

第四個是誰?andyer,這個倒霉的傢伙。為什麼是begin()+3而不是+4? 我開始寫這篇文章的時候也沒有在意,後來在ilovevc 的提醒下,發現了這個問題。begin()是第乙個,begin()+1是第二個,... begin()+3當然就是第四個了。

1.7 partition 和stable_partition

好像這兩個函式並不是用來排序的,'分類'演算法,會更加貼切一些。partition就是把乙個區間中的元素按照某個條件分成兩類。其函式原型為:

template

<

class forwarditerator,

class predicate>

forwarditerator partition(forwarditerator first, forwarditerator last, predicate pred)

template

<

class forwarditerator,

class predicate>

forwarditerator stable_partition(forwarditerator first, forwarditerator last, predicate pred);

看看應用吧:班上10個學生,計算所有沒有及格(低於60分)的學生。你只需要按照下面格式替換1.4中的程式:

stable_sort(vect.begin(), vect.end(),less());

替換為:

student exam("

pass", 60); stable_partition(vect.begin(), vect.end(), bind2nd(less(), exam));

其輸出結果為:

------before sort... tom: 74 jimy: 56 mary: 92 jessy: 85 jone: 56 bush: 52 winter: 77 andyer: 63 lily: 76 maryia: 89 -----after sort .... jimy: 56 jone: 56 bush: 52 tom: 74 mary: 92 jessy: 85 winter: 77 andyer: 63 lily: 76 maryia: 89

看見了嗎,jimy,jone, bush(難怪說美國**比較笨

2 sort 和容器

stl中標準容器主要vector, list, deque, string, set, multiset, map, multimay, 其中set, multiset, map, multimap都是以樹結構的方式儲存其元素詳細內容請參看:學習stl map, stl set之資料結構基礎. 因此在這些容器中,元素一直是有序的。

這些容器的迭代器型別並不是隨機型迭代器,因此,上述的那些排序函式,對於這些容器是不可用的。上述sort函式對於下列容器是可用的:

如果你自己定義的容器也支援隨機型迭代器,那麼使用排序演算法是沒有任何問題的。

對於list容器,list自帶乙個sort成員函式list::sort(). 它和演算法函式中的sort差不多,但是list::sort是基於指標的方式排序,也就是說,所有的資料移動和比較都是此用指標的方式實現,因此排序後的迭代器一直保持有效(vector中sort後的迭代器會失效).

3 選擇合適的排序函式

為什麼要選擇合適的排序函式?可能你並不關心效率(這裡的效率指的是程式執行時間), 或者說你的資料量很小, 因此你覺得隨便用哪個函式都無關緊要。

其實不然,即使你不關心效率,如果你選擇合適的排序函式,你會讓你的**更容易讓人明白,你會讓你的**更有擴充性,逐漸養成乙個良好的習慣,很重要吧

如果你以前有用過c語言中的qsort, 想知道qsort和他們的比較,那我告訴你,qsort和sort是一樣的,因為他們採用的都是快速排序。從效率上看,以下幾種sort演算法的是乙個排序,效率由高到低(耗時由小變大):

partion

stable_partition

nth_element

partial_sort

sort

stable_sort

記得,以前翻譯過effective stl的文章,其中對如何選擇排序函式總結的很好:

總之記住一句話:如果你想節約時間,不要走彎路, 也不要走多餘的路!

4 小結

討論技術就像個無底洞,經常容易由一點可以引申另外無數個技術點。因此需要從全域性的角度來觀察問題,就像觀察stl中的sort演算法一樣。其實在stl還有make_heap, sort_heap等排序演算法。本文章沒有提到。本文以例項的方式,解釋了stl中排序演算法的特性,並總結了在實際情況下應如何選擇合適的演算法。

5 參考文件

條款31:如何選擇排序函式

the standard librarian: sorting in the standard library

effective stl中文版

standard template library programmer's guide

詳細解說 STL 排序 Sort

從效率上看,以下幾種sort演算法的是乙個排序,效率由高到低 耗時由小變大 partion stable partition nth element partial sort sort stable sort 若需對vector,string,deque,或 array容器進行全排序,你可選擇sor...

希爾排序詳細解說

了解了插入排序後,希爾排序就可以迎刃而解了 可以將整個陣列分為gap組,這裡的gap array.length 2,然後進行插入排序,再將gap 2,再次進行插入排序,直到gap 1的時候,就可以得到最終的已排序陣列 1.資料量少的時候,速度快 2.資料接近有序的時候,速度快 時間複雜度 最好 o ...

選擇排序詳細解說

選擇排序是每一次從無序區間選出最大 或最小 的乙個元素,存放在無序區間的bound位置,直到全部待排序的資料元 素排完 本文章中以公升序為例,讓已排序的序列中的最後乙個元素為bound,讓cur初始值為bound 1 就是未排序的第乙個元素 然後和bound位置的值進行比較,如果bound位置的元素...