Shah Shishir
Shah Shishir

Reputation: 191

Is it possible to get a single element of a set in C++ STL?

I have the following C++ code with C++ STL vector,

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

It normally prints the element that is stored into the 10th index. The output be 10.

But I tried the same thing with C++ STL set also,

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

It gives me Compilation error showing the following messages :(

prog.cpp: In function ‘int main()’:

prog.cpp:12:18: error: no match for ‘operator[]’ (operand types are ‘std::set’ and ‘int’) cout << myset[10] << endl;

So, my question is, is there any way to print any element of STL sets alike the STL vectors in C++? if yes, how?

Meanwhile we can use iterators but it can work with the full set, as far I know. :)

Upvotes: 1

Views: 14452

Answers (4)

Ivaylo Valchev
Ivaylo Valchev

Reputation: 10415

Yes, it's possible, but not using operator[].

std::set doesn't provide operator[] as it isn't a random-access container. Instead, one must use iterators to access its elements.

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

Note that std::set is an ordered container and the elements will not appear in the order you inserted them.

Upvotes: 12

bebidek
bebidek

Reputation: 592

You can't do it in clear C++, but if you use GCC (and you probably do, based on your compilation error), you can create policy based set, which behaves as normal STL set, but supports operation you asked about.

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

In the code above, we define structure called indexed_int_set, which has 2 additional methods: find_by_order(int p) and order_of_key(int k). First one is what you want, it returns an iterator to p-th element. Second one is similar to lower_bound, but returns an index instead of iterator.

Upvotes: 1

Shashwat Kumar
Shashwat Kumar

Reputation: 5287

You cannot access set elements by index. However you can use std::advance on iterator.

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

std::next is also there in C++11,

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

The Difference between this two Versions is explained here: What's the difference between std::advance and std::next?

Upvotes: 5

the problem is that sets don't have access by index. but you still can do something like:

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

which is basically getting an interator and "moving it" forward 9 places...

Upvotes: 2

Related Questions