在很多應用中,排序都是至關重要的,而且很多 stl 演算法也只適用於有序物件序列。定義在 algorithm 標頭檔案中的函式模板 sort() 缺省會將元素段排成公升序,這也就意味著排序的物件的型別需要支援<
運算子。
物件也必須是可交換的,這說明可以用定義在 utility 標頭檔案中的函式模板 swap() 來對兩個物件進行交換。這進一步表明這種物件的型別需要實現移動建構函式和移動賦值運算子。
函式模板 sort() 的型別引數 iter 是元素段元素對應的迭代器型別,而且它們必須支援隨機訪問迭代器。這表明 sort() 演算法只能對提供隨機訪問迭代器的容器中的元素進行排序,也說明 sort() 只能接受 array、vector、deque 或標準陣列中的元素。可以回顧前面章節,list 和 forward_list 容器都有成員函式 sort(); 這些用來排序的特殊成員函式是必要的,因為 list 只提供雙向迭代器,且 forward_list 只提供正向迭代器。
可以從函式呼叫的引數中推導出 sort() 的模板型別引數,它們是定義被排序物件範圍的迭代器。當然,迭代器型別隱式定義了這個元素段中物件的型別。下面是乙個使用 sort() 演算法的示例:
sort() 呼叫將 number 容器的全部元素排成公升序,然後用 copy() 演算法輸出結果。可以不必對容器的全部內容進行排序。下面這條語句對 numbers 中除了第乙個和最後乙個元素之外的元素進行了排序:std::vectornumbers ;
std::sort(std::begin(numbers), std::end(numbers));
std::copy(std::begin(numbers), std::end(numbers),std:: ostream_iterator) ;
// output: 11 22 33 44 66 77 88 99
std::sort(++std::begin(numbers),--std::end(numbers));
為了將元素排成降序,需要提供乙個用來比較元素的函式物件,作為 sort() 的第三個引數:
std::sort(std::begin(numbers), std::end(numbers), std::greater<>());
這個比較函式必須返回布林值,而且有兩個引數,它們要麼是迭代器解引用後得到的型別,要麼是迭代器解引用後可以隱式轉換成的型別。引數可以是不同型別的。只要比較函式滿足這些條件,它就可以是你喜歡的任何樣子,也包括 lambda 表示式。例如:
這段**對 deque 容器 words 中的 string 元素進行了排序,並且輸出了排序後的結果。這裡的比較函式是乙個 lambda 表示式,它們用每個單詞的最後乙個字母來比較排序的順序。結果元素以它們最後乙個字母的降序來排序。std::dequewords ;
std::sort(std::begin(words), std::end(words),(const string& s1, const string& s2) );
std::copy(std::begin(words), std::end(words),
std::ostream_iterator); // six four two one nine nine one three five
下面在乙個簡單的示例中介紹 sort() 的用法。這裡會先從鍵盤讀取 name 物件,然後將它們按公升序排列,再輸出結果。name 類定義在 name.h 標頭檔案中,它包含下面這些**:
這個流插入和提取運算子被定義為 name 物件的友元函式。可以將 operator<() 定義為類的成員函式,但為了展示如何為 sort() 演算法指定比較函式引數,這裡沒有定義它。下面是程式**:#ifndef name_h
#define name_h
#include // for string class
class name
; std::string second {};
public:
name(const std::string& name1, const std::string& name2) : first(name1), second(name2){}
name()=default;
std::string get_first() const
std::string get_second() const
friend std::istream& operator>>(std::istream& in, name& name);
friend std::ostream& operator<<(std::ostream& out, const name& name);
};// stream input for name objects
inline std::istream& operator>>(std::istream& in, name& name)
// stream output for name objects
inline std::ostream& operator<<(std::ostream& out, const name& name)
#endif
main() 中的一切幾乎都是使用 stl 模板完成的。names 容器用來儲存從 cin 讀入的姓名。輸入由 copy() 演算法執行,它使用乙個 istream_iterator例項讀入 name 物件。 istream_iterator預設的建構函式會建立流的結束迭代器。copy() 函式用 back_insert_iterator() 建立的 back_inserter迭代器將輸入的每個物件複製到 names 中。為 name 類過載的流運算子允許使用流迭代器來輸入和輸出 name 物件。// sorting class objects
#include // for standard streams
#include // for string class
#include // for vector container
#include // for stream and back insert iterators
#include // for sort() algorithm
#include "name.h"
int main()
); std::cout << "\nthe names in ascending sequence are:\n";
std::copy(std::begin(names), std::end(names), std::ostream_iterator(std::cout, "\n"));
}
name 物件的比較函式是用 lambda 表示式定義的,它是 sort() 演算法的第三個引數。如果想將 operator<() 定義為 name 類的成員函式,可以省略這個引數。然後用 copy() 演算法將排序後的 names 寫入標準輸出流,它會將前兩個引數指定範圍內的元素複製到作為第三個引數的 ostream_iterator物件中。
下面是示例輸出:
對 names 的排序只考慮了姓。當姓相同時,可以將 lambda 表示式擴充套件為可以比較名。你可能會好奇在這個示例中為什麼不用 pair來表示姓名,這比定義乙個新的類要簡單多了。顯然我們可以這麼做,但卻沒有定義類這麼清楚明了。enter names as first name followed by second name. enter ctrl+z to end:
jim jones
bill jones
jane smith
john doe
janet jones
willy schaferknaker
^z6 names read. sorting in ascending sequence...
the names in ascending sequence are:
john doe
jim jones
bill jones
janet jones
willy schaferknaker
jane smith
STL sort之結構體排序
sort函式的三個引數 第乙個 開始值的位址 第二個 結束值的位址 第三個 排序的函式,若沒有則預設為公升序排列 記住函式return中大於為降序,小於為公升序。現在說對結構體陣列的排序 include include using namespacestd struct node arr 100 b...
STL sort演算法中的比較函式
排序,既陌生又熟悉的名詞。排序,成為面試官中喜歡問的演算法問題。c stl中為我們提供了std sort,所以今天我們不是來描述各種排序演算法的實現,而是看看怎麼使用stl為我們提供的sort。先預熱,include include include int main person int age,s...
STL sort函式 對map按值排序
問題 要對以map中的資料進行按value排序 難點 map中的資料是按照key排序的,用for迴圈進行迭代器輸出的順序,就是按照key排序的順序。但是按value排序就不可能了。方案 stl中的sort函式原型 include using namespace std template void s...