【问题标题】:Is it possible to get a single element of a set in C++ STL?是否可以在 C++ STL 中获取集合的单个元素?
【发布时间】:2025-12-06 04:25:01
【问题描述】:

我有以下带有 C++ STL 向量的 C++ 代码,

#include <iostream>
#include <vector>
using namespace std;

int main ()
{   
    vector <int> v;

    for (int i=0; i<15; i++)
        v.push_back (i);

    cout << v[10] << endl;

    return 0;
}

它通常打印存储在第 10 个索引中的元素。输出为 10。

但我也尝试了同样的 C++ STL 设置,

#include <iostream>
#include <set>
using namespace std;

int main ()
{
    set <int> myset;

    for (int i=0; i<15; i++)
        myset.insert (i);

    cout << myset[10] << endl;

    return 0;
}

它给了我编译错误,显示以下消息:(

prog.cpp:在函数“int main()”中:

prog.cpp:12:18: error: no match for ‘operator[]’(操作数类型是 ‘std::set’ 和 ‘int’) cout

所以,我的问题是,有什么方法可以打印 STL 集合的任何元素,就像 C++ 中的 STL 向量一样?如果是,怎么做?

同时,我们可以使用迭代器,但据我所知,它可以与完整的集合一起使用。 :)

【问题讨论】:

  • 迭代器应该可以解决问题。
  • 因为 set 没有索引访问权限。
  • 您的示例是一个玩具,但您应该记住 std::set 不存储重复项。如果您每次都将循环重写为 insert(1) 会怎样——您怎么知道 10 在范围内?即使使用迭代器,您也会越界访问项目,因为该集合仅包含 1 个项目。
  • 我的意思是,如果您依赖 [ ] 访问 std::set 中的项目,那么您的程序存在设计缺陷。
  • 顺便问一下,你确定你真的想要集合的“第 10 个元素”吗?我的意思是,集合中的顺序对你来说重要吗?

标签: c++ c++11 vector stl set


【解决方案1】:

是的,可以,但不能使用operator[]

std::set 不提供operator[],因为它不是随机访问容器。相反,必须使用迭代器来访问它的元素。

auto first = myset.begin(); // get iterator to 1st element
std::advance(first, 9);     // advance by 9
std::cout << *first;        // 10th element

请注意,std::set 是一个有序容器,元素不会按照您插入它们的顺序出现。

【讨论】:

  • s/will not/may not/ 我们应该强调这是使用集合的错误方式。容器之间预期用途的差异正是存在不同容器的原因。为什么向量有 6 个不同的名称?
【解决方案2】:

您不能通过索引访问集合元素。但是你可以在迭代器上使用std::advance

set<int>::iterator it = myset.begin();
std::advance(it, 5); // advanced by five

std::next也在C++11中,

auto it = std::next(myset.begin(), 5);

这里解释了这两个版本之间的区别: What's the difference between std::advance and std::next?

【讨论】:

    【解决方案3】:

    问题是集合不能通过索引访问。 但您仍然可以执行以下操作:

    set<int>::iterator myIterator = myset.begin();
    advance(myIterator , 9);
    int theTenth= *myIterator;
    

    这基本上是获得一个交互器并将其“移动”向前 9 个位置......

    【讨论】:

      【解决方案4】:

      您不能在清晰的 C++ 中执行此操作,但如果您使用 GCC(根据您的编译错误,您可能会这样做),您可以创建基于策略的集合,其行为与普通 STL 集合一样,但支持您要求的操作关于。

      #include <iostream>
      using namespace std;
      
      #include <ext/pb_ds/assoc_container.hpp>
      using namespace __gnu_pbds;
      typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> indexed_int_set;
      
      int main ()
      {
          indexed_int_set myset;
      
          for (int i=0; i<15; i++)
              myset.insert (i);
      
          cout << *myset.find_by_order(10) << endl;
      
          return 0;
      }
      

      在上面的代码中,我们定义了名为indexed_int_set的结构体,它有两个额外的方法:find_by_order(int p)order_of_key(int k)。 第一个是你想要的,它返回一个迭代器到第 p 个元素。 第二个类似于lower_bound,但返回一个索引而不是迭代器。

      【讨论】:

        最近更新 更多