多图和矢量之间的数据结构

时间:2010-08-11 10:25:37

标签: c++ stl

  

可能重复:
  A std::map that keep track of the order of insertion?

我正在寻找一个像std :: multimap一样工作的STL容器,但我可以像vector一样按插入顺序访问成员。

例如:

  multimap<char,int> mymultimap;
  multimap<char,int>::iterator it;

  mymultimap.insert ( pair<char,int>('a',100) );
  mymultimap.insert ( pair<char,int>('z',150) ); 
  mymultimap.insert ( pair<char,int>('b',75) );
  mymultimap.insert ( pair<char,int>('a',75) );

  for ( it=mymultimap.begin() ; it != mymultimap.end(); it++ )
    cout << (*it).first << " => " << (*it).second << endl;

输出:

a =&gt; 100

a =&gt; 75

b =&gt; 75

z =&gt; 150

预期产出:

a =&gt; 100

z =&gt; 150

b =&gt; 75

a =&gt; 75

感谢。

4 个答案:

答案 0 :(得分:2)

您可以使用std::vector<std::pair<char,int> >。此外,您可以使用std::make_pair函数创建一对。以下是示例代码:

vector<pair<char,int> > v;
    vector<pair<char,int> >::iterator it;

  v.push_back ( make_pair('a',100) );
  v.push_back ( make_pair('z',150) ); 
  v.push_back ( make_pair('b',75) );
  v.push_back ( make_pair('a',75) );

  for ( it=v.begin() ; it != v.end(); it++ )
    cout << (*it).first << " => " << (*it).second << endl;

答案 1 :(得分:1)

boost库有一个灵活的多索引容器,可以执行您想要的操作以及更多内容:http://www.boost.org/doc/libs/1_43_0/libs/multi_index/doc/index.html

您可以构建可以按顺序访问的multi_index容器,但也允许O(log(N))快速查找。开始时语法有点不透明,但是一旦你得到了一些工作,这是一项值得的投资,因为实现将由boost人员和大量普通用户进行全面测试。

答案 2 :(得分:0)

除了已经建议的std::vector<std::pair<char,int> >之外,boost::bimap可能是一个很好的解决方案。

答案 3 :(得分:0)

您可以将multimaplist合并。

以下是一个可以满足您需求的容器。对象存储在multimap和其他list存储多图迭代器中(只要指向的元素在容器中,它们就保持有效)。所有操作都具有与multimap相同的复杂性,除了{em> O(n * m)的erase方法,其中 n 是所有元素的数量, m 是删除的元素数。

#include <map>
#include <list>
#include <algorithm>

template <class Key, class T>
class my_map : public std::multimap<Key, T> {
public:
    typedef typename std::multimap<Key, T> multimap_type;

    typedef typename multimap_type::key_type   key_type;
    typedef typename multimap_type::value_type value_type;
    typedef typename multimap_type::size_type  size_type;
    typedef typename multimap_type::iterator   iterator;

    struct order_iterator : std::list<typename multimap_type::iterator>::iterator {
        typedef typename std::list<typename multimap_type::iterator>::iterator iterator_t;

        order_iterator() {}
        order_iterator(const iterator_t &iterator) : iterator_t(iterator) { }

        const std::pair<const Key, T>& operator *  () const { return ***(const iterator_t*)this; }
              std::pair<const Key, T>& operator *  ()       { return ***(      iterator_t*)this; }
        const std::pair<const Key, T>* operator -> () const { return &**this; }
              std::pair<const Key, T>* operator -> ()       { return &**this; }
    };

private:
    std::list<typename multimap_type::iterator> list;
    multimap_type *base() { return this; }

public:
    order_iterator order_begin() { return this->list.begin(); }
    order_iterator order_end() { return this->list.end(); }

    iterator insert(const value_type& x)
    {
        iterator ret = this->base()->insert(x);
        this->list.push_back(ret);
        return ret;
    }

    iterator insert(iterator position, const value_type& x)
    {
        iterator ret = this->base()->insert(position, x);
        this->list.push_back(ret);
        return ret;
    }

    template <class InputIterator>
    void insert(InputIterator first, InputIterator last)
    {
        while (last != first) this->insert(first++);
    }

    void erase(iterator first, iterator last)
    {
        if (first == this->end()) return;

        for (iterator it = first; it != last; ++it) {
            this->list.erase(std::find(this->list.begin(), this->list.end(), it));
        }
    }

    void erase(iterator position)
    {
        iterator last = position;
        this->erase(position, ++last);
    }

    size_type erase (const key_type& x)
    {
        iterator range_begin = this->lower_bound(x);
        if (range_begin == this->end()) return 0;

        size_type ret = 0;
        iterator range_end = range_begin;
        do range_end++, ret++; while (range_end != this->end() && range_end->first == x);

        this->base()->erase(range_begin, range_end);
        for (; range_begin != range_end; range_begin++) {
            this->list.erase(std::find(this->list.begin(), this->list.end(), range_begin));
        }

        return ret;
    }

    void clear()
    {
        this->list.clear();
        this->base()->clear();
    }
};

#include <iostream>
using namespace std;

my_map<char,int> mymultimap;

void dump()
{
    cout << "by insert:\n";
    for (
        my_map<char,int>::order_iterator it = mymultimap.order_begin();
        it != mymultimap.order_end();
        it++
    ) {
        cout << (*it).first << " => " << (*it).second << endl;
    }

    cout << "by key:\n";
    for (
        my_map<char,int>::iterator it = mymultimap.begin();
        it != mymultimap.end();
        it++
    ) {
        cout << (*it).first << " => " << (*it).second << endl;
    }

    cout << endl;
}

int main()
{
    mymultimap.insert(make_pair('a',100));
    mymultimap.insert(make_pair('z',150));
    mymultimap.insert(make_pair('b',75));
    mymultimap.insert(make_pair('a',75));
    dump();

    mymultimap.erase('a');
    dump();
}

如果更频繁地使用插入顺序中的迭代元素然后通过键进行查找,那么“镜像”该想法将更为理想:将键/值对存储在list中(因此我们可以迭代插入()并且还有multiset个包含list个元素的迭代器(用于按键查找)。