我应该在C ++中使用什么样的数据结构

时间:2012-02-23 07:16:45

标签: c++

我需要一些东西来表示一对序列的序列,如下所示:

[((1,2) (1,3)) ((1,2) (1,4) (1,5))].

我还需要自由地附加对的序列来制作一对对的序列,比如append.[((1 2)(3 4)) ((5 6))] = ((1 2)(3 4)(5 6)). C ++中是否有任何易于使用的东西可以让我像这样操作我的数据?

4 个答案:

答案 0 :(得分:5)

  

我需要一些东西来代表一对序列的序列

有三个标准的序列容器模板 - std::vector,一个动态数组; std::list,一个双向链表;和std::deque,类似于数组的东西,允许在两端有效插入。 C ++ 11还添加了std::forward_list,一个单链表。 vector通常是最佳选择,除非您有特定的使用模式推荐其他一个。

有一个标准的对模板std::pair,它有两个任意类型的对象作为名为firstsecond的成员。

因此,您的结构可以表示为vector<vector<pair<int,int> > >

  

我还需要自由地附加对的序列以制作一对序列

有各种方法可以做到这一点;一个是

#include <algorithm> // for std::copy
#include <iterator>  // for std::back_inserter
#include <vector>    // for std::vector
#include <utility>   // for std::pair

typedef std::pair<int,int> pair;
typedef std::vector<pair> sequence;
typedef std::vector<sequence> seqseq;

sequence flatten(seqseq const & in) {
    sequence out;
    for (seqseq::const_iterator s = in.begin(); s != in.end(); ++s) {
        std::copy(s->begin(), s->end(), std::back_inserter(out));
    }
    return out;
}

如果您的序列非常长,并且您不需要保留原始序列,则使用链接列表可能更有效,并通过拼接附加它们 - 这会将大量元素从一个列表移动到另一个列表中恒定时间,不复制它们:

#include <vector>    // for std::vector
#include <list>      // for std::list
#include <utility>   // for std::pair

typedef std::pair<int,int> pair;
typedef std::list<pair> sequence;
typedef std::vector<sequence> seqseq;

sequence flatten(seqseq & in) {
    sequence out;
    for (seqseq::iterator s = in.begin(); s != in.end(); ++s) {
        out.splice(out.end(), *s);
    }

    // The input only contains empty lists now - we might as well clean up
    in.clear();

    return out;
}

答案 1 :(得分:4)

听起来你可能需要一对配对列表,甚至是一对配对列表,这取决于我如何解析你的要求: - )

您可以查看std::queuestd::deque列表方面,std::pair查看对方面。请点击链接了解详情。

作为起点,请参阅以下代码:

#include <iostream>
#include <queue>
#include <utility>

int main (void) {
    std::queue <std::pair <int,int> > xyzzy = std::queue <std::pair <int,int> > ();

    std::pair <int,int> p1 = std::pair <int,int> (3, 9);
    xyzzy.push (p1);

    std::pair <int,int> p2 = xyzzy.front();
    xyzzy.pop();
    std::cout << p2.first << ' ' << p2.second << '\n';

    return 0;
}

这会创建一个整数对的队列,推送一个整数并将其弹出 - 实际上你需要一个front/pop组合,因为queue::pop只需删除最旧的元素而不是回归它 - 为什么那些选择忽视几十年的常规做法超出了我: - )

然后打印出构成该对的两个整数。

这应该足以说明实现你的东西所需的所有操作和数据类型。


话虽如此,Mike Seymour在评论中提出了有效的观点。如果在“列表”中需要非类似队列的行为,则应该选择向量而不是队列或双端队列。

向量允许您获取列表中的随机元素,而不仅仅是头部或尾部。

缺点是你可能会失去有效的排队能力,如果这很重要 - 没有简单的方法来推动一个元素在向量的前面,只在最后,并从前面弹出可能效率低下。这是可行的,但不太可能那么有效,因为它不是为什么设计矢量:

然而,随机访问能力可能值得牺牲。

以下代码显示了如何使用向量而不是队列,如果需要,包括类似队列的行为:

#include <iostream>
#include <vector>
#include <utility>

int main (void) {
    std::pair <int,int> p1;
    std::vector <std::pair <int,int> > xyzzy;

    xyzzy = std::vector <std::pair <int,int> > ();

    for (int i = 0; i < 10; i++) {
        p1 = std::pair <int,int> (i, i * i);
        xyzzy.push_back (p1);
    }

    while (xyzzy.size() > 0) {
        std::pair <int,int> p2 = xyzzy.at(0);
        xyzzy.erase (xyzzy.begin());
        std::cout << p2.first << ' ' << p2.second << '\n';
    }

    return 0;
}

输出为:

0 0
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81

答案 2 :(得分:3)

试试这个:

std::vector<std::vector<std::pair<int, int> > >

答案 3 :(得分:0)

您的任务最自然的数据结构应该是对的列表列表:即

#include <list>
#include <boost/assign/list_of.hpp>
#include <boost/assert.hpp>

int main_seq_assign(int, char **)
{
    using namespace std;
    using namespace boost::assign;

    typedef pair<int, int> t_rec;
    typedef list<t_rec> t_recs;
    typedef list<t_recs> t_data;

    t_recs  a = list_of<t_rec>(1, 2) (1, 3),
            b = list_of<t_rec>(1, 2) (1, 4) (1, 5);
    t_data  c = list_of<t_recs>(a)(b);
    t_data  d = list_of<t_recs>(list_of<t_rec>(1, 2) (1, 3))
                               (list_of<t_rec>(1, 2) (1, 4) (1, 5));

    t_data  e;
    e.insert(e.end(), a);
    e.insert(e.end(), b);

    BOOST_ASSERT(c == d && c == e);
}