c++中std::set自定义去重和排序函数
c++中的std::set,是基于紅黑樹的平衡二叉樹的數據結構實現的一種容器,因為其中所包含的元素的值是唯一的,因此主要用于去重和排序。這篇文章的目的在于探討和分享如何正確使用std::set實現去重和排序功能。
方法一:使用std::set內置的less比較函數(直接定義內置類型的set對象)
這種方法適用于:1)比較int、char等內置類型。2)只能針對某一個內置類型去重和排序:如果想通過id(int)去重,并通過hot(int)排序,該種方法就束手無策了。代碼如下:
#include <iostream> #include <set> using namespace std; void main() {std::set<int> mySet; // 直接定義內置類型set集合mySet.insert(10); // 默認比較函數為lessmySet.insert(20); // 從小到大排序for(auto it:mySet) {std::cout<<it<<std::endl;}std::cout<<"end"<<std::endl;}結果如下: output:1020end方法二:自定義類(結構體)比較函數
前文提到:直接定義內置類型的set對象,即使用std::set內置的默認的less比較函數,可能不能滿足我們的實際需求。例如:現在有一批結構體對象,需要將其插入set集合,并按照id去重,按照熱度hot進行排序。這個時候,就需要重新自定義比較函數了。有兩種方法可以自定義比較函數:
重載<操作符
為甚么要重載<運算符呢?能不能重載”<=”或者”>=”運算符?答案是不可以。幾乎所有的方法或容器都需要排序來滿足數學意義上的標準嚴格弱序化,否則這些方法或容器的行為將不可預知。假設f(x,y)是一個比較函數。 如果該函數滿足如下條件則它是嚴格弱序化的。
1. f(x,x) = false; 2. if f(x,y) then !f(y,x) 3. if f(x,y) and f(y,z) then f(x,z) 4. if !f(x,y)&&!f(y,x) then x==y; if x==y and y==z then x==z;看上去有點暈乎,不過不用擔心,只要你的比較方法能夠滿足對相等元素永遠返回false(記住一個準則:永遠讓比較函數對相同元素返回false),那你的方法就滿足要求了。
其實,set容器在判定已有元素a和新插入元素b是否相等時,是這么做的:
1)將a作為左操作數,b作為有操作數,調用比較函數,并返回比較值
2)將b作為左操作數,a作為有操作數,再調用一次比較函數,并返回比較值。
如果1、2兩步的返回值都是false,則認為a、b是相等的,則b不會被插入set容器中
如果1、2兩步的返回值都是true,則可能發生未知行為
因此,記住一個準則:永遠讓比較函數對相同元素返回false。
#include <iostream> #include <set> using namespace std; struct song {int m_id;int m_hot;song(int id,int hot){this->m_id = id;this->m_hot = hot;}bool operator<(const struct song & right)const //重載<運算符{if(this->m_id == right.m_id) //根據id去重return false;else{if(this->m_hot != right.m_hot){return this->m_hot > right.m_hot; //降序}else{return this->m_id > right.m_id; }}} }; void main() {std::set<song> mySet;song s1(10,100);song s2(20,200);song s3(20,300);song s4(30,200);mySet.insert(s1); //插入s1mySet.insert(s2); //插入s2mySet.insert(s3); //s3和s2的id相同,不插入mySet.insert(s4); //插入s4for(auto it:mySet){std::cout<<"id:"<<it.m_id<<",hot:"<<it.m_hot<<std::endl;}std::cout<<"end"<<std::endl; };結果如下: id:30,hot : 200 id:20,hot : 200 id:10,hot : 100 end重載()運算符
具體代碼如下:
#include <iostream> #include <set> using namespace std; struct song {int m_id;int m_hot;song(int id,int hot){this->m_id = id;this->m_hot = hot;}/*bool operator<(const struct song & right)const //重載<運算符{if(this->m_id == right.m_id) //根據id去重return false;else{if(this->m_hot != right.m_hot){return this->m_hot > right.m_hot; //降序}else{return this->m_id > right.m_id; }}}*/ }; struct comp {bool operator()(struct song left,struct song right) //重載()運算符{if(left.m_id == right.m_id) //根據id去重return false;else{if(left.m_hot != right.m_hot){return left.m_hot > right.m_hot; //降序}else{return left.m_id > right.m_id; }}}}; void main() {std::set<song,comp> mySet; //寫法和2.1中的的區別song s1(10,100);song s2(20,200);song s3(20,300);song s4(30,200);mySet.insert(s1); //插入s1mySet.insert(s2); //插入s2mySet.insert(s3); //s3和s2的id相同,不插入mySet.insert(s4); //插入s4for(auto it:mySet){std::cout<<"id:"<<it.m_id<<",hot:"<<it.m_hot<<std::endl;}std::cout<<"end"<<std::endl; }; 復制代碼 結果如下: id:30,hot : 200 id:20,hot : 200 id:10,hot : 100 end總結
以上是生活随笔為你收集整理的c++中std::set自定义去重和排序函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 更改Android Studio中AVD
- 下一篇: CodeForces - 560E Ge