保留队列中的唯一元素

时间:2015-02-22 09:29:54

标签: c++ vector

我有以下形式的矢量队列:

queue<vector<unsigned> > a;
vector<unsigned> b;
b.push_back(10); b.push_back(12); b.push_back(15);
a.push(b);
vector<unsigned> b2;
b1.push_back(15); b1.push_back(19); b1.push_back(18);
vector<unsigned> b1;
b1.push_back(10); b1.push_back(12); b1.push_back(15);

我想在队列中只输入唯一的向量。例如,在上面的例子中,我想保留向量元素:(10,12,15),(15,19,18),即在这里我删除了重复元素:(10,12,15)并保留了它复制一次。

检查队列中是否已存在向量的方法之一是迭代它。有没有其他方法可以检查队列中是否已经存在一个向量或者没有效率?

我正在使用gcc版本:gcc(Ubuntu / Linaro 4.6.3-1ubuntu5)4.6.3

3 个答案:

答案 0 :(得分:2)

如果插入顺序很重要,那么我会使用第二个数据结构来跟踪唯一插入的元素,例如std::set

#include <cassert>
#include <iostream>
#include <queue>
#include <set>
#include <vector>

template <typename T>
class unique_queue {
private:
    std::queue<T> m_queue;
    std::set<T> m_set;
public:
    bool push(const T& t) {
        if (m_set.insert(t).second) {
            m_queue.push(t);
            return true;
        }
        return false;
    }

    void pop() {
        assert(!m_queue.empty());
        const T& val = front();

        typename std::set<T>::iterator it = m_set.find(val);
        assert(it != m_set.end());

        m_set.erase(it);
        m_queue.pop();
    }

    const T& front() const {
        return m_queue.front();
    }
};

int main(int argc, char *argv[]) {
    unique_queue<std::vector<unsigned> > q;

    std::vector<unsigned> b1;
    b1.push_back(10); b1.push_back(12); b1.push_back(15);
    std::cout << "pushed: " << q.push(b1) << std::endl;

    std::vector<unsigned> b2;
    b2.push_back(15); b2.push_back(17); b2.push_back(18);
    std::cout << "pushed: " << q.push(b2) << std::endl;

    std::vector<unsigned> b3;
    b3.push_back(10); b3.push_back(12); b3.push_back(15);
    std::cout << "pushed: " << q.push(b3) << std::endl;

    q.pop();
    q.pop();
    std::cout << "pushed: " << q.push(b3) << std::endl;
}

默认情况下,std::set<T>会使用std::less<T>来比较其元素。对于std::vector<unsigned>,这可以归结为按字母顺序比较将数据插入集合中的向量。

答案 1 :(得分:1)

队列不是通过元素值进行有效搜索的数据结构(它们本质上就像向量)。集合是,但它们不保证元素的排序。

使用std::unique尝试提供与实际队列组织相关的最佳解决方案。

答案 2 :(得分:1)

如果您有这样的特殊要求,我倾向于不直接使用标准容器。相反,我首先定义一个接口:

class my_queue {
public:
    typedef vector<unsigned> element_type;
    void push(element_type const&);
    bool empty() const;
    element_type pop();

然后,由于您希望元素是唯一的,我将使用常规队列和集合:

private:
    queue<element_type> m_queue;
    set<element_type> m_set;
};

我认为你明白了这一点,我懒得启动编译器来实际测试它。 ;)

进一步说明:

  • 尽管它更复杂,但矢量只是一种数据类型,因此可以对其进行分配,复制和比较。这种比较用于例如std::set
  • 这可以进行优化,因为两者中的数据存储实际上是多余的。然后,我将实际元素存储在集合中,并将它们的顺序存储在队列中(即存储集迭代器)。
  • 除非您在队列中存储了许多元素,否则对队列进行线性搜索(例如使用std :: deque作为替换)可能是性能更佳的替代方案。
  • 目前尚不清楚插入副本是否会影响订单。如果元素已被删除然后再添加,该怎么办?在任何情况下,编写测试以确保队列具有所需的行为。