Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Boost或C+中是否有容器+;11哪个作为队列但具有唯一元素?_C++_Boost_C++11 - Fatal编程技术网

C++ Boost或C+中是否有容器+;11哪个作为队列但具有唯一元素?

C++ Boost或C+中是否有容器+;11哪个作为队列但具有唯一元素?,c++,boost,c++11,C++,Boost,C++11,我正在寻找一个像std::queue这样的容器,它将在末尾添加元素(例如,一个带有id类型uint)的自定义类),但前提是该对象不在容器中 只有当id相等时,类的两个元素才被视为相等(我重载了运算符==) C++11或Boost中是否存在这样的容器?这称为带合并的队列。天真的实现是使用如下内容: std::set<your_key_t> unique; std::queue<your_data_t> q; void enqueue(your_data_t x) {

我正在寻找一个像
std::queue
这样的容器,它将在末尾添加元素(例如,一个带有
id
类型
uint
)的自定义类),但前提是该对象不在容器中

只有当
id
相等时,类的两个元素才被视为相等(我重载了运算符
==


C++11或Boost中是否存在这样的容器?

这称为带合并的队列。天真的实现是使用如下内容:

std::set<your_key_t> unique;
std::queue<your_data_t> q;

void enqueue(your_data_t x) {
    if (unique.insert(x.key).second) {
        q.push(std::move(x));
    }
}

your_data_t dequeue(your_data_t dflt) {
    if (!q.empty()) {
        your_data_t x = std::move(q.front()); q.pop();
        unique.erase(q.front().key);
        return x;
    }
    else return dflt;
}
std::设置唯一性;
std::队列q;
无效排队(您的数据){
if(唯一。插入(x键)。秒){
q、 推(std::move(x));
}
}
您的\u数据\u t出列(您的\u数据\u t dflt){
如果(!q.empty()){
您的_data_t x=std::move(q.front());q.pop();
唯一。擦除(q.front().key);
返回x;
}
否则返回dflt;
}
一个不太简单的实现可能是以某种非平凡的方式(比如覆盖)将传入数据与队列中的数据合并,而不是仅仅删除更新。

除了,下面是另一个示例,说明如何组合*并使用要查找的属性形成容器

template <typename T>
class QueueUnique {
public:
    void push(T t) {
        if (set_.insert(t).second) {
            queue_.push(std::move(t));
        }
    }
    T& front() { return queue_.front(); }
    T& back() { return queue_.back(); }
    typename std::set<T>::size_type size() { return set_.size(); }
    /* More functions */
private:
    std::set<T> set_;
    std::queue<T> queue_;
};
模板
类队列唯一{
公众:
无效推力(T){
if(设置插入(t).second){
队列推送(std::move(t));
}
}
T&front(){返回队列u.front();}
T&back(){返回队列u.back();}
typename std::set::size_type size(){return set_u.size();}
/*更多功能*/
私人:
std::set_u2;;
std::队列;
};
像这样使用:

QueueUnique<int> q;
q.push(1);
q.push(1);
q.push(2);
q.push(3);
q.push(1);

std::cout << "Size: " << q.size() << std::endl;   // Size: 3
std::cout << "Front: " << q.front() << std::endl; // Front: 1
std::cout << "Back: " << q.back() << std::endl;   // Back: 3
q;
q、 推(1);
q、 推(1);
q、 推(2);
q、 推(3);
q、 推(1);

这主意不错,+1。但由于OP要求使用C++11,
无序集
几乎肯定会更好,因为它有O(1)插入、搜索和删除。另外,
set
要求OP define
操作符将其更改为使用
unordered\u set
是微不足道的,而且这个想法已经被清楚地解释了。@SchighSchagh-当你盲目地建议
unordered\u map
具有不确定的访问延迟时,当你声称它是
O(1)时,你应该非常小心
当它实际上是
O(N)
,并且忘记了定义了相应的
std::hash
(或自定义)的键以便与
无序映射一起使用时
两个备注:(1)它是
唯一的.erase()
(而不是
唯一的.remove()
)。(2) 为了获得强大的异常安全保证(前提是
您的\u data\u t
移动构造函数(如果存在)允许),交换行
unique.erase(q.front().key)
您的_data_t x=std::move(q.front())@bobah这不是一个盲目的建议。是的,最坏的情况是O(N),但平均情况是O(1),具有良好的散列。在OP的例子中,他使用
uint
作为键,因此
std::hash
就可以了。虽然肯定会有一些病理情况下,
无序集
的表现比
差,但这些情况在实践中极为罕见和/或人为造成的。顺便说一句,
set
也有不确定的访问延迟(一半节点位于深度
log(n)
,另一半不在;树可能需要重新平衡,等等)。为什么需要
push()
的参数作为右值引用