【问题标题】:Storing (x, y) Coordinates with set使用集合存储 (x, y) 坐标
【发布时间】:2019-06-26 21:59:33
【问题描述】:

我需要帮助将一组 (x, y) 坐标存储在一个集合中。 我存储它的方式是

set<int> s;
s.insert( (1, 1) );
s.insert( (1, 3) );
s.insert( (3, 1) );
s.insert( (3, 3) );

for (auto x: s) {
     cout << x << endl;
}

但它不会打印出 (1, 1), (1, 3).... 并打印出 1, 3。

我对 c++ 很陌生,如果有人能给我建议如何用集合存储这些值,我将不胜感激!

【问题讨论】:

  • 使用std::set&lt;std::pair&lt;int&gt;&gt; 怎么样?还要检查逗号运算符的实际作用。
  • 由于用户必须手动输入坐标,我需要能够检查它是否是唯一坐标,并且我读到该集合具有唯一功能

标签: c++


【解决方案1】:

您的代码会发生以下情况:

s 是std::set&lt;int&gt; 类型,因此适合存储int 类型的变量。

调用函数std::set&lt;int&gt;::insert 需要int 类型的参数。如果你使用s.insert((1, 3)),你实际上并没有插入pair,而是使用comma-operator。它的工作原理如下:在表达式a, b 中,表达式a 被求值,然后表达式b 被求值,表达式b 的结果作为整个表达式的结果返回。你可以在这里阅读更多信息:How does the Comma Operator work。

因此s.insert((1, 3)) 导致s.insert(3) 和3 被插入到s。

要实现所需的行为,您可以使用std::pair,在标题utility 中定义。可能的方法如下:

std::set<std::pair<int, int>> s;
s.insert(std::make_pair(1, 1));
s.insert(std::make_pair(1, 3));
s.insert(std::make_pair(3, 1));
s.insert(std::make_pair(3, 3));

for (const auto& e : s) 
  std::cout << "(" << e.first << ", " << e.second << ") ";

输出:

(1, 1) (1, 3) (3, 1) (3, 3)

使用初始化列表插入对的附加语法如下:

s.insert({1, 3});

如果您想就地构造对而不是构造和插入它们,可以使用std::set::emplace,如下所示:

s.emplace(1, 3);

【讨论】:

    【解决方案2】:

    我认为你的意思是使用对,pair 是一个类,将一对可以翻译为坐标 x,y 的值耦合在一起

    set<std::pair<int,int>> s;
    
    s.insert({ 1, 1 });
    s.insert({ 1, 3 });
    s.insert({ 3, 1 });
    s.insert({ 3, 3 });
    
    for (auto x : s) {
        std::cout << x.first<< " "<<x.second << std::endl;
    }
    
    // to print the first & the last element
    
        auto start = s.begin();
        auto last=s.rbegin();
    
        std::cout << start->first << " " << start->second << " " << last->first << " " << last->second<<'\n';
    
     // for the nth element
     int n=2;
     auto nelement=std::next(s.begin(), n);
     std::cout<<nelement->first<<" "<<nelement->second;
    

    【讨论】:

    • 请问是否可以只打印一组的第一对和最后一对?
    • 它可以迭代它,但它会被排序(所以它们的顺序不完全相同)例如:输入 {2,1,5} 如果你迭代它将是 {1, 2,5} 但插入返回对插入元素的引用,因此您可以执行以下操作:在您的第一个插入中 auto first = s.insert({1,1}); & 最后插入相同
    • 我希望它被订购所以它很好,但我只需要打印出第一对和最后一对,有没有办法打印第 n 个元素?
    • 检查编辑
    • 谢谢!但我可以知道什么是 rbegin() 吗?为什么不结束()?
    【解决方案3】:

    set&lt;int&gt; 只能存储 一个 int,而不是 两个(在单个 insert 操作中)。如果您写s.insert( (1, 3) );,您显然是在尝试插入2,这是行不通的。它似乎以某种方式起作用,但实际上语法正在对你玩一个讨厌的把戏!

    在这种情况下,表达式(1, 3) 使用comma operator,它的作用是:计算 1(它是 1),把它扔掉,然后计算3,这显然是3,这就是返回的内容: 3. 所以你的语句实际上相当于s.insert(3);。这就是为什么您没有收到编译错误的原因。但显然这不是你想要的。

    要解决此问题,您必须使用一次存储两个值的集合。有一种数据类型,称为std::pair!

    所以你可以像这样声明它

    set<std::pair<int,int>> s;
    

    并像插入数据一样

    s.insert({1, 3});
    

    【讨论】:

    • 请问是否可以只打印出第一对和最后一对?我读过使用迭代器,但无法让它工作
    • @user3413646 是的,有可能,但顺序可能与插入顺序不同。 std::set 使用树状数据结构来存储其元素。想象一个包含整数的集合,其构造如下:std::set&lt;int&gt; {5, 2 , -1, 2} 如果您遍历集合并打印元素,您将得到-1, 2, 5 而不是5, 2, -1, 2。如果您需要保留顺序,另一个 STL 容器是更好的选择。请参阅 this question 了解如何迭代集合。
    猜你喜欢
    • 2022-01-19
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 2022-01-16
    • 1970-01-01
    • 2011-03-08
    相关资源
    最近更新 更多