Reputation: 28147
Can I somehow overload any of std::multiset's operators (like you do with '()' to create a custom comapre function) so that when 2 elements in the multiset are swapped, so are another 2 elements from another vector linked to those?
I mean, I actually want to insert let's say elemetns {a,b,c,d,e} in the multiset, but I also want to keep track of their position inside the multiset, without having to use .find(). So I thought about creating another vector pos, where pos[k] is the position of element k in the multiset.
So, if I have this vector pos, I still must make the multiset when I insert an element in it, not to only put it in the right place in the multiset, but also change the pos[] of all elements swapped.
I don't exactly know how multiset changes/swaps it's element to sort them, but can I somehow override that so instead of:
swap(a,b);
I'll have something like.
swap(pos[a],pos[b]);
swap(a,b)
And if you have any other ideas of how could I keep track of an element's position inside a multiset, without using the .find() (which has O(N) complexity for equal elements) would be great!
EDIT
And also, I guess that I have to change something so that when I insert a new element (n) it will get the right initialization for pos[n]
, before any "swaps" are made.
Upvotes: 2
Views: 1614
Reputation: 372814
As an alternative, you may want to look into the order statistic tree data structure, which has the following functionality all working in O(log n) time:
In other words, you can ask the tree for elements by position or by key, and can have the tree tell you what position a given element is at. It also stores the elements in sorted order (like std::multiset
) and can easily be made to handle duplicate elements. In short, it can be used like a std::multiset
that efficiently supports indexing.
This seems like it might be the best approach, though unfortunately order statistic trees aren't in the C++ standard library. You'd need to find a third-party library for them.
Hope this helps!
Upvotes: 2
Reputation: 76828
You cannot override these without inheriting from multiset
, which is not recommended. So what you need is the logic to track the positions of the elements in your multiset
.
If you insert an element into the multiset
, you get an iterator to that element. You can use that to determine the element before the one you inserted, and from that determine the new position:
std::multiset<your_item_type> it = your_set.insert(item);
std::size_t new_element_pos = it != your_set.begin() ? pos[*(it--)] + 1
: pos[*(it++)] - 1
The important part is that now you have to update all positions of items after the one you inserted, by increasing them by one.
To keep track of swaps, you can simply specialize std::swap
for your type, and when two elements are swapped, you swap their positions in the position-vector.
Upvotes: 0