Queue with unique entries in c++

后端 未结 4 988
生来不讨喜
生来不讨喜 2021-02-05 07:25

I need to implement a queue containing unique entries(no duplicates) in C or C++. I am thinking of maintaining a reference of elements already available in queue but that seems

4条回答
  •  萌比男神i
    2021-02-05 07:56

    std::queue is a container adaptor and uses relatively few members of the underlying Container. You can easily implement a custom container that contains both: an unordered_map of reference_wrapper and a deque. It needs at least members front and push_back. Check inside that hash_map when push_back of your container is called and reject accordingly (possibly throw). To give the complete example:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    namespace std {
    
    // partial specialization for reference_wrapper
    // is this really necessary?
    template
    class hash> {
    public:
      std::size_t operator()(std::reference_wrapper x) const 
      { return std::hash()(x.get()); }
    };
    
    }
    
    template 
    class my_container {
      // important: this really needs to be a deque and only front
      // insertion/deletion is allowed to not get dangling references
      typedef std::deque storage;
      typedef std::reference_wrapper c_ref_w;
      typedef std::reference_wrapper ref_w;
    public:  
      typedef typename storage::value_type value_type;
      typedef typename storage::reference reference; 
      typedef typename storage::const_reference const_reference; 
      typedef typename storage::size_type size_type;
    
      // no move semantics
      void push_back(const T& t) {
        auto it = lookup_.find(std::cref(t));
        if(it != end(lookup_)) {
          // is already inserted report error
          return;
        }
        store_.push_back(t);
        // this is important to not have dangling references
        lookup_.insert(store_.back());
      }
    
      // trivial functions
    
      bool empty() const { return store_.empty(); }
      const T& front() const { return store_.front(); }
      T& front() { return store_.front(); }
    
      void pop_front() { lookup_.erase(store_.front()); store_.pop_front();  }
    private:
      // look-up mechanism
      std::unordered_set lookup_;
      // underlying storage
      storage store_;
    };
    
    int main()
    {
      // reference wrapper for int ends up being silly 
      // but good for larger objects
      std::queue> q;
      q.push(2);
      q.push(3);
      q.push(2);
      q.push(4);
      while(!q.empty()) {
        std::cout << q.front() << std::endl;
        q.pop();
      }
    
      return 0;
    }
    

    EDIT: You will want to make my_container a proper model of container (maybe also allocators), but this is another full question. Thanks to Christian Rau for pointing out bugs.

提交回复
热议问题