您好,登錄后才能下訂單哦!
如何在C++中使用STL關聯式容器自定義排序規(guī)則?相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。
1) 使用函數對象自定義排序規(guī)則
#include <iostream> #include <set> // set #include <string> // string using namespace std; //定義函數對象類 class cmp { public: //重載 () 運算符 bool operator ()(const string &a,const string &b) { //按照字符串的長度,做升序排序(即存儲的字符串從短到長) return (a.length() < b.length()); } }; int main() { //創(chuàng)建 set 容器,并使用自定義的 cmp 排序規(guī)則 std::set<string, cmp>myset{"http://jb51.net.net/stl/", "http://jb51.net.net/python/", "http://jb51.net.net/java/"}; //輸出容器中存儲的元素 for (auto iter = myset.begin(); iter != myset.end(); ++iter) { cout << *iter << endl; } return 0; }
程序執(zhí)行結果為:
http://jb51.net.net/stl/
http://jb51.net.net/java/
http://jb51.net.net/python/
重點分析一下 6~13 行代碼,其定義了一個函數對象類,并在其重載 () 運算符的方法中自定義了新的排序規(guī)則,即按照字符串的長度做升序排序。在此基礎上,程序第 17 行代碼中,通過將函數對象類的類名 cmp 通過 set 類模板的第 2 個參數傳遞給 myset 容器,該容器內部排序數據的規(guī)則,就改為了以字符串的長度為標準做升序排序。
需要注意的是,此程序中創(chuàng)建的 myset 容器,由于是以字符串的長度為準進行排序,因此其無法存儲相同長度的多個字符串。
另外,C++ 中的 struct 和 class 非常類似(有關兩者區(qū)別,可閱讀《C++ struct和class到底有什么區(qū)別》一文),前者也可以包含成員變量和成員函數。因此上面程序中,函數對象類 cmp 也可以使用 struct 關鍵字創(chuàng)建:
//定義函數對象類 struct cmp { //重載 () 運算符 bool operator ()(const string &a, const string &b) { //按照字符串的長度,做升序排序(即存儲的字符串從短到長) return (a.length() < b.length()); } };
值得一提的是,在定義函數對象類時,也可以將其定義為模板類。比如:
//定義函數對象模板類 template <typename T> class cmp { public: //重載 () 運算符 bool operator ()(const T &a, const T &b) { //按照值的大小,做升序排序 return a < b; } };
注意,此方式必須保證 T 類型元素可以直接使用關系運算符(比如這里的 < 運算符)做比較。
其實在 STL 標準庫中,本就包含幾個可供關聯式容器使用的排序規(guī)則,如表 1 表示。
表 1 C++ STL標準庫適用于關聯式容器的排序規(guī)則
排序規(guī)則 | 功能 |
---|---|
std::less<T> | 底層采用 < 運算符實現升序排序,各關聯式容器默認采用的排序規(guī)則。 |
std::greater<T> | 底層采用 > 運算符實現降序排序,同樣適用于各個關聯式容器。 |
std::less_equal<T> | 底層采用 <= 運算符實現升序排序,多用于 multimap 和 multiset 容器。 |
std::greater_equal<T> | 底層采用 >= 運算符實現降序排序,多用于 multimap 和 multiset 容器。 |
值得一提的是,表 1 中的這些排序規(guī)則,其底層也是采用函數對象的方式實現的。以 std::less<T> 為例,其底層實現為:
template <typename T> struct less { //定義新的排序規(guī)則 bool operator()(const T &_lhs, const T &_rhs) const { return _lhs < _rhs; } }
在此基礎上,當關聯式容器中存儲的數據類型為自定義的結構體變量或者類對象時,通過對現有排序規(guī)則中所用的關系運算符進行重載,也能實現自定義排序規(guī)則的目的。
注意,當關聯式容器中存儲的元素類型為結構體指針變量或者類的指針對象時,只能使用函數對象的方式自定義排序規(guī)則,此方法不再適用。
舉個例子:
#include <iostream> #include <set> // set #include <string> // string using namespace std; //自定義類 class myString { public: //定義構造函數,向 myset 容器中添加元素時會用到 myString(string tempStr) :str(tempStr) {}; //獲取 str 私有對象,由于會被私有對象調用,因此該成員方法也必須為 const 類型 string getStr() const; private: string str; }; string myString::getStr() const{ return this->str; } //重載 < 運算符,參數必須都為 const 類型 bool operator <(const myString &stra, const myString & strb) { //以字符串的長度為標準比較大小 return stra.getStr().length() < strb.getStr().length(); } int main() { //創(chuàng)建空 set 容器,仍使用默認的 less<T> 排序規(guī)則 std::set<myString>myset; //向 set 容器添加元素,這里會調用 myString 類的構造函數 myset.emplace("http://jb51.net.net/stl/"); myset.emplace("http://jb51.net.net/c/"); myset.emplace("http://jb51.net.net/python/"); // for (auto iter = myset.begin(); iter != myset.end(); ++iter) { myString mystr = *iter; cout << mystr.getStr() << endl; } return 0; }
程序執(zhí)行結果為:
http://jb51.net.net/c/
http://jb51.net.net/stl/
http://jb51.net.net/python/
在這個程序中,雖然 myset 容器表面仍采用默認的 std::less<T> 排序規(guī)則,但由于我們對其所用的 < 運算符進行了重載,使得 myset 容器內部實則是以字符串的長度為基準,對各個 mystring 類對象進行排序。
另外,上面程序以全局函數的形式實現對 < 運算符的重載,還可以使用成員函數或者友元函數的形式實現。其中,當以成員函數的方式重載 < 運算符時,該成員函數必須聲明為 const 類型,且參數也必須為 const 類型:
bool operator <(const myString & tempStr) const { //以字符串的長度為標準比較大小 return this->str.length() < tempStr.str.length(); }
至于參數的傳值方式是采用按引用傳遞還是按值傳遞,都可以(建議采用按引用傳遞,效率更高)。
同樣,如果以友元函數的方式重載 < 運算符時,要求參數必須使用 const 修飾:
//類中友元函數的定義 friend bool operator <(const myString &a, const myString &b); //類外部友元函數的具體實現 bool operator <(const myString &stra, const myString &strb) { //以字符串的長度為標準比較大小 return stra.str.length() < strb.str.length(); }
看完上述內容,你們掌握如何在C++中使用STL關聯式容器自定義排序規(guī)則的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。