Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with `std::set`?

Tags:

In the other topic I was trying to solve this problem. The problem was to remove duplicate characters from a std::string.

std::string s= "saaangeetha"; 

Since the order was not important, so I sorted s first, and then used std::unique and finally resized it to get the desired result:

aeghnst 

That is correct!


Now I want to do the same, but at the same time I want the order of characters intact. Means, I want this output:

sangeth 

So I wrote this:

template<typename T> struct is_repeated {     std::set<T>  unique;     bool operator()(T c) { return !unique.insert(c).second; } };  int main() {     std::string s= "saaangeetha";     s.erase(std::remove_if(s.begin(), s.end(), is_repeated<char>()), s.end());      std::cout << s ; } 

Which gives this output:

saangeth 

That is, a is repeated, though other repetitions gone. What is wrong with the code?

Anyway I change my code a bit: (see the comment)

template<typename T> struct is_repeated {     std::set<T> & unique;  //made reference!     is_repeated(std::set<T> &s) : unique(s) {} //added line!     bool operator()(T c) { return !unique.insert(c).second; } };  int main() {     std::string s= "saaangeetha";     std::set<char> set; //added line!     s.erase(std::remove_if(s.begin(),s.end(),is_repeated<char>(set)),s.end());      std::cout << s ; } 

Output:

sangeth 

Problem gone!

So what is wrong with the first solution?

Also, if I don't make the member variable unique reference type, then the problem doesn't go.

What is wrong with std::set or is_repeated functor? Where exactly is the problem?

I also note that if the is_repeated functor is copied somewhere, then every member of it is also copied. I don't see the problem here!

like image 819
Nawaz Avatar asked Mar 22 '11 20:03

Nawaz


People also ask

What is the complexity of different std::set operations?

std::set is commonly implemented as a red-black binary search tree. Insertion on this data structure has a worst-case of O(log(n)) complexity, as the tree is kept balanced.

What is std::set?

std::set is an associative container that contains a sorted set of unique objects of type Key . Sorting is done using the key comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Sets are usually implemented as red-black trees.

Is set in CPP sorted?

As mentioned above, sets in C++ are the type of STL containers that are used for storing elements in a sorted way. The operations allowed to be performed on sets are insertion and deletion. The elements are internally sorted according to a strict weak ordering in a set type container.

Is std::set ordered?

The elements in the container follow a strict order at all times. All inserted elements are given a position in this order.


1 Answers

Functors are supposed to be designed in a way where a copy of a functor is identical to the original functor. That is, if you make a copy of one functor and then perform a sequence of operations, the result should be the same no matter which functor you use, or even if you interleave the two functors. This gives the STL implementation the flexibility to copy functors and pass them around as it sees fit.

With your first functor, this claim does not hold because if I copy your functor and then call it, the changes you make to its stored set do not reflect in the original functor, so the copy and the original will perform differently. Similarly, if you take your second functor and make it not store its set by reference, the two copies of the functor will not behave identically.

The reason that your final version of the functor works, though, is because the fact that the set is stored by reference means that any number of copies of tue functor will behave identically to one another.

Hope this helps!

like image 138
templatetypedef Avatar answered Jan 28 '23 19:01

templatetypedef