【问题标题】:Is it possible to remove queue element by value?是否可以按值删除队列元素?
【发布时间】:2011-12-04 01:10:40
【问题描述】:

我想从队列中删除具有特定值的元素。怎么做这样的事情? (我正在尝试创建地图和队列的并发混合,目前我尝试在this answer 上实现)

所以我目前有这样的代码:

#ifndef CONCURRENT_QUEUED_MAP_H
#define CONCURRENT_QUEUED_MAP_H

#include <map>
#include <deque>
#include <boost/thread.hpp>
#include <boost/thread/locks.hpp>

template <class map_t_1, class map_t_2>
class concurrent_queued_map
{
private:
    std::map<map_t_1, map_t_2> _ds;
    std::deque<map_t_1> _queue;
    mutable boost::mutex mut_;
public:
    concurrent_queued_map() {}

    map_t_2 get(map_t_1 key) {
        boost::mutex::scoped_lock lock(mut_);
        return _ds[key];
    }

    map_t_1 put(map_t_1 key, map_t_2 value) {
        boost::mutex::scoped_lock lock(mut_);
        _ds.insert(std::pair<map_t_1, map_t_2>(key,value));
        _queue.push_back(key);
        return key;
    }

    map_t_2 get_last(map_t_1 key) {
        boost::mutex::scoped_lock lock(mut_);
        const map_t_1 k = _queue.front();
        return _ds[k];
    }

    void remove_last(map_t_1 key) {
        boost::mutex::scoped_lock lock(mut_);
        const map_t_1 k = _queue.front();
        _ds.erase(k);
        _queue.pop_front();
    }

    void remove(map_t_1 key) {
        boost::mutex::scoped_lock lock(mut_);
        _queue.erase(std::remove(_queue.begin(), _queue.end(), key), _queue.end());
        _ds.erase(k);
    }

    int size() {
        boost::mutex::scoped_lock lock(mut_);
        return _ds.size();
    }

};

#endif // CONCURRENT_QUEUED_MAP_H

那我该怎么办?如何按值从队列中删除?或者是否有任何类似于队列的 STL 或 Boost 组件?这意味着它将具有.front()pop_front();push_back(key); 并且还支持按值搜索和擦除?

【问题讨论】:

  • 你能把你的问题表述得更清楚更简洁吗?队列没有“键”,所以你的问题没有意义;它是一个只有 values. 的序列容器

标签: c++ stl queue std


【解决方案1】:

这样做 - 队列和地图都消除了使用其中任何一个的优点,并保留了两者的缺点(至少在性能方面)。我会简单地使用deque&lt;std::pair&lt;map_t_1, map_t_2&gt; &gt; 来表示映射和双端队列。然后地图查找或编辑需要遍历整个双端队列,因此效率不高。

更有效的解决方案将更难实现,因为您正在尝试处理两种不同的索引方案 - 按键(映射)和按索引(通过排序性质 od deque 需要)。为了有效地做到这一点,我会提出自我实现的双链表(作为队列),并将键映射到linked_list条目。在添加/添加队列时,双链表条目还将包含用于在映射中查找的键。

【讨论】:

  • 是否有任何开箱即用的组件?
  • 我不是 boost 专家,但我猜没有。
【解决方案2】:

deque 是一个序列容器,所以你只能通过 value 删除元素,最好使用 remove/erase idiom:

std::deque<T> q;
T val;

q.erase(std::remove(q.begin(), q.end(), val), q.end());

如果您使用的是std::queue 适配器,那么您根本无法执行此操作,因为该适配器仅公开了front/back 接口,并不用于迭代或查找语义。

如果您选择将队列实现为std::list,请改用成员函数remove()

【讨论】:

  • q.erase(val)q.erase(std::remove(q.begin(), q.end(), val), q.end()); 之间有什么区别?
  • @Kabumbus 不同的是,第一个不会编译,因为erase 采用迭代器而不是包含类型的值。
猜你喜欢
  • 2015-04-25
  • 1970-01-01
  • 2010-12-30
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-02
  • 2017-11-19
相关资源
最近更新 更多