简体   繁体   中英

Creating ordered multiset with correctly working find()

I tried to create ordered multiset with such code:

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef long long ll;

template <class type1>
using ordered_multiset = tree <type1, null_type, less_equal <type1>, rb_tree_tag, tree_order_statistics_node_update>;

ordered_multiset <ll> kek;

int main()
{
    kek.insert(1); kek.insert(1);
    kek.insert(2); kek.insert(2); kek.insert(2);
    kek.insert(3);
    cout << (kek.find(2) == kek.end()) << endl;
}

But find() cant find any number because of using less_equal < ll > comparator instead of less < ll > . So, how to save dublicates in sorted set with working right find() ?

From the gnu docs here

Brace onself: this library does not contain containers like std::multimap or std::multiset. Instead, these data structures can be synthesized via manipulation of the Mapped template parameter.

There is no way to use this data structure for a multiset without some boiler plate of your own. For example your might do something like the following (though this is an unsafe incomplete implementation)

template <class T>
class multiset_equal_list {
    friend operator<(const multiset_equal_list<T>&, const T&);
private:
    mutable std::vector<T> equals;
public:
    bool operator<(const T& arg) const { return equals[0] < arg; }
    void add_equal(const T& arg) const { equals.push_back(arg); }
}


template <class T>
class my_multiset {
private:
    std::set<multiset_equal_list<T>> values; //instead of set, you can use the __gnu_pbds tree
public:
    void insert(const T& arg) {
        auto it = values.lower_bound(arg);
        if (it == values.end() || (*it < arg)) {
            multiset_equal_list<T> to_add;
            to_add.add_equal(arg);
            values.insert(it, to_add);
        } else { //they are equal
            it->add_equal(arg);
        }
    }
}

The link goes more into how you might approach the problem in different ways, but you are likely better off rolling your own or using an existing library that has all the functionality you want in a more portable standard way.

Note that the reason using std::less_equal does not work for you is because tree (and set and multiset etc.) determine equivalence if the comparison evaluates false for both. eg. a is equivalent to b if !(a < b) && !(b < a) . So using less_equal that can never be the case (barring overloading)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM