Std: set udtf in c ++, stdset
Std: set in c ++ is a container based on the data structure of the balanced binary tree of the red and black trees, because the values of the elements contained in it are unique, therefore, it is mainly used for deduplication and sorting. The purpose of this article is to explore and share how to use std: set to achieve de-weighting and sorting.
1. Method 1: Use the std: set built-in less comparison function (directly define the built-in type of set object)
This method applies to: 1) Compare built-in types such as int and char. 2) Only one built-in type can be de-duplicated and sorted: If you want to de-duplicate by id (int) and sort by hot (int), this method is useless. The Code is as follows:
1 # include <iostream> 2 # include <set> 3 using namespace std; 4 void main () 5 {6 std: set <int> mySet; // directly define the built-in type set 7 mySet. insert (10); // The default comparison function is less 8 mySet. insert (20); // sort 9 for (auto it: mySet) 10 {11 std: cout <it <std: endl; 12} 13 std: cout <"end" <std: endl; 14 15}
The result is as follows:
Output: 10 20 end
2. Method 2: User-defined class (struct) Comparison Function
As mentioned above: You can directly define a set object of the built-in type, that is, use the default less comparison function built in std: set, which may not meet our actual needs. For example, if you have a batch of struct objects, You need to insert them into the set, de-duplicate them by id, and sort them by hot. At this time, you need to re-define the comparison function. There are two ways to customize the comparison function:
2.1 overload <Operator
Why do I need to overload the <operator? Can I overload the "<=" or "> =" operator? The answer is no. Almost all methods or containers need to be sorted to meet the strictly weak ordering standards in the mathematical sense, otherwise the behavior of these methods or containers will be unpredictable. Assume that f (x, y) is a comparison function. If the function meets the following conditions, it is strictly deprecated.
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;
It looks a bit dizzy, but don't worry, as long as your comparison method can always return false for equal elements (remember a criterion: always let the comparison function return false for the same element ), then your method meets the requirements.
In fact, the set container does this when determining whether the existing element a and the newly inserted element B are equal: 1) Use a as the left operand, B as the operand, and call the comparison function, return the Compare value 2) use B as the left operand, And a as the operand. Call the Compare function again and return the Compare value. If the return values of steps 1 and 2 are both false, B is considered to be equal, and B is not inserted into the set container. If the return values of steps 1 and 2 are true, therefore, the comparison function always returns false to the same element.
# 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 // overload <operator {if (this-> m_id = right. m_id) // return false Based on the id; else {if (this-> m_hot! = Right. m_hot) {return this-> m_hot> right. m_hot; // descending order} 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); // insert s1 mySet. insert (s2); // insert s2 mySet. insert (s3); // s3 and s2 have the same id and do not insert mySet. insert (s4); // insert s4 for (auto it: mySet) {std: cout <"id:" <it. m_id <", hot:" <it. m_hot <std: endl;} std: cout <"end" <std: endl ;};
Result: id: 30, hot: 200id: 20, hot: 200id: 10, hot: 100
End
2.2 overload () Operator
The Code is as follows:
1 # include <iostream> 2 # include <set> 3 using namespace std; 4 struct song 5 {6 int m_id; 7 int m_hot; 8 song (int id, int hot) 9 {10 11 this-> m_id = id; 12 this-> m_hot = hot; 13} 14/* 15 bool operator <(const struct song & right) const // overload <operator 16 {17 if (this-> m_id = right. m_id) // return false according to id; 19 else20 {21 if (this-> m_hot! = Right. m_hot) 22 {23 return this-> m_hot> right. m_hot; // descending order 24} 25 else26 {27 return this-> m_id> right. m_id; 28} 29} 30} 31 */32}; 33 struct comp 34 {35 bool operator () (struct song left, struct song right) // overload () operator 36 {37 38 if (left. m_id = right. m_id) // remove 39 return false Based on id; 40 else41 {42 if (left. m_hot! = Right. m_hot) 43 {44 return left. m_hot> right. m_hot; // 45} 46 else47 {48 return left. m_id> right. m_id; 49} 50 51} 52} 53 54}; 55 void main () 56 {57 std: set <song, comp> mySet; // differences between the write method and 2.1: 58 song s1 (10,100); 59 song s2 (20,200); 60 song s3 (20,300); 61 song s4 (30,200); 62 mySet. insert (s1); // insert s163 mySet. insert (s2); // insert s264 mySet. insert (s3); // s3 and s2 have the same id and do not insert 65 mySet. insert (s4); // insert s466 for (auto it: mySet) 67 {68 std: cout <"id:" <it. m_id <", hot:" <it. m_hot <std: endl; 69} 70 std: cout <"end" <std: endl; 71 };
Result: id: 30, hot: 200id: 20, hot: 200id: 10, hot: 100
End