简体   繁体   English

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

[英]What kind of data structure should I use for this in C++

I need something to represent a sequence of sequences of pairs, like this: 我需要一些东西来表示一对序列的序列,如下所示:

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

I also need to append the sequences of pairs freely to make one sequence of pairs, like this append.[((1 2)(3 4)) ((5 6))] = ((1 2)(3 4)(5 6)). 我还需要自由地附加对的序列以产生一对序列,如此append.[((1 2)(3 4)) ((5 6))] = ((1 2)(3 4)(5 6)). Is there anything that is simple to use in C++ that could let me manipulate my data like this? 在C ++中是否有任何易于使用的东西可以让我像这样操纵我的数据?

I need something to represent a sequence of sequences of pairs 我需要一些东西来表示一对序列的序列

There are three standard sequence container templates - std::vector , a dynamic array; 有三个标准的序列容器模板std::vector ,一个动态数组; std::list , a doubly-linked list; std::list ,一个双向链表; and std::deque , an array-like thing that allows efficient insertion at both ends. std::deque ,类似于数组的东西,允许在两端有效插入。 C++11 also adds std::forward_list , a singly-linked list. C ++ 11还添加了std::forward_list ,一个单链表。 vector is usually the best choice, unless you have particular usage patterns that recommend one of the others. vector通常是最佳选择,除非您有特定的使用模式推荐其他的一个。

There is a standard pair template, std::pair , which has two objects of arbitrary types as members called first and second . 有一个标准的对模板std::pair ,它有两个任意类型的对象作为firstsecond成员。

So your structure can be represented as vector<vector<pair<int,int> > > . 因此,您的结构可以表示为vector<vector<pair<int,int> > >

I also need to append the sequences of pairs freely to make one sequence of pairs 我还需要自由地附加对的序列以产生一对序列

There are various ways of doing that; 有各种方法可以做到这一点; one is 一个是

#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;
}

If your sequences are very long, and you don't need to preserve the original sequences, it might be more efficient to use linked lists, and append them by splicing - this moves large numbers of elements from one list to another in constant time, without copying them: 如果你的序列非常长,并且你不需要保留原始序列,那么使用链表可能更有效,并通过拼接来附加它们 - 这会在一定时间内将大量元素从一个列表移动到另一个列表,没有复制它们:

#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;
}

It sounds like you may need a list of pairs, or even a list of lists of pairs, depending on how I parse your requirements :-) 听起来你可能需要一对配对列表,甚至是一对配对列表,这取决于我如何解析你的要求:-)

You can look into std::queue or std::deque for the list aspect, and std::pair for the pair aspect. 您可以查看列表方面的std::queuestd::deque ,以及对方面的std::pair Follow the links for details. 请点击链接了解详情。

As a starting point, see the following code: 作为起点,请参阅以下代码:

#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;
}

This creates a queue of pairs of integers, pushes one on and pops it off - you actually need a front/pop combo for this since the queue::pop simply deletes the oldest element rather than returning it - why those chose to ignore decades of common practice is beyond me :-) 这会创建一个整数对的队列,推送一个整数并弹出它 - 你实际上需要一个front/pop组合,因为queue::pop删除最旧的元素而不是返回它 - 为什么那些选择忽略几十年常见做法超出我的范围:-)

It then prints out the two integer constituting the pair. 然后打印出构成该对的两个整数。

That should hopefully be enough to illustrate all the operations and data types you'll need to implement your stuff. 这应该足以说明实现您的东西所需的所有操作和数据类型。


Having said that, Mike Seymour makes a valid point in the comments. 话虽如此,Mike Seymour在评论中提出了一个有效的观点。 If you need non-queue-like behaviour in your "lists", you should probably opt for a vector rather than a queue or deque. 如果在“列表”中需要非类似队列的行为,则应该选择向量而不是队列或双端队列。

Vectors allow you to get at random elements within the list rather than just the head or tail. 向量允许您获取列表中的随机元素,而不仅仅是头部或尾部。

The downside is that you may lose the efficient queuing ability if that's important - there's no easy way to push an element at the front of the vector, only at the end, and popping from the front is likely to be inefficient. 缺点是你可能会失去有效的排队能力,如果这很重要 - 没有简单的方法来推动一个元素在向量的前面 ,只在最后,并从前面弹出可能是低效的。 It's doable but unlikely to be that efficient, since it's not what vectors were designed for: 这是可行的,但不太可能那么有效,因为它不是为什么矢量设计的:

Still, the random access ability may be worth the sacrifice. 然而,随机访问能力可能值得牺牲。

The following code shows how to use a vector instead of a queue, including the queue-like behaviour if you need it: 以下代码显示了如何使用向量而不是队列,如果需要,还包括类似队列的行为:

#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;
}

with the output being: 输出为:

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

尝试这个:

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

The most natural data structure for your task should be a list of list of pairs : ie 任务的最自然的数据结构应该是对列表的列表 :即

#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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM