std :: set <key,comparator,=“”allocator =“”>

时间:2017-07-07 21:43:50

标签: c++ set stdset

我最近尝试使用set来保留trie中的一些配置。

我发现比较器存在疑问,例如:

    #include <iostream>
    #include <set>

    using namespace std;

    struct Node{
      int position;
      int reference;
      Node(int r, int p){
        this->position = p;
        this->reference = r;
      }
    };

    struct Node_c{
      const bool operator()(const Node& n1, const Node& n2){
        // return n1.reference != n2.reference;
        // i've tried some functions here, like n1.reference != n2.reference ? true : n1.position < n2.position;  
      }
    };


    int main(){
      set<Node, Node_c> aNodes;

      aNodes.emplace(1,1);
      aNodes.emplace(1, 2); // i dont want to add this one, the reference already exists and the position is bigger than the last one
      aNodes.emplace(1, 0); // i want to replace the (1,1) for this one


      for(auto nd : aNodes){
        cout << nd.reference << ' ' << nd.position << '\n';
      }
    }

如何按顺序保留节点较小的节点,但不包括等于引用?

感谢。

2 个答案:

答案 0 :(得分:3)

使用std::set的单一方法无法做到这一点,因为它严格要求其元素具有唯一键!

set.emplace要么插入元素,要么没有,但它不会替换现有元素,请参阅the documentation

最适合您的解决方案可能是使用std::map<int, int> position映射到reference,如果值变小则更新值,或者继续使用{{} 1}}并编写一个自定义方法,首先检查该集合是否包含一个元素,如果是,则仅在新std::set较小时替换它

此外,您的比较器应该比较小于(reference),而不是不等于(<

答案 1 :(得分:1)

#include <iostream>
#include <set>

struct Node {
    int position;
    int reference;

    Node(int r, int p)
            : position(p), reference(r) {
    }
};


struct NodeSet {
    struct AscendingReference {
        bool operator()(const Node &n1, const Node &n2) const {
            return n1.reference < n2.reference;
        }
    };

    struct SmallerPosition {
        bool operator()(const Node &n1, const Node &n2) const {
            return n1.position < n2.position;
        }
    };

    using Storage = std::set<Node, AscendingReference>;

    auto &propose(Node n) {
        auto ifind = storage_.find(n);
        if (ifind != std::end(storage_)) {
            if (not SmallerPosition()(n, *ifind))
                return *ifind;
            storage_.erase(ifind);
        }
        return *(storage_.insert(std::move(n)).first);
    }

    auto begin() const { return storage_.begin(); }

    auto end() const { return storage_.end(); }

private:
    Storage storage_;
};


int main() {
    NodeSet aNodes;

    aNodes.propose(Node(1, 1));
    aNodes.propose(Node(1, 2));
    aNodes.propose(Node(1, 0));

    for (auto nd : aNodes) {
        std::cout << nd.reference << ' ' << nd.position << '\n';
    }
}