#c #c 14
#c #stl
Вопрос:
У меня есть набор типов set<int>
, и я хочу получить итератор в какое-то место, которое не является началом.
Я делаю следующее:
set<int>::iterator it = myset.begin() 5;
Мне любопытно, почему это не работает и каков правильный способ получить итератор туда, куда я хочу.
Комментарии:
1. C и C — это разные языки.
Ответ №1:
myset.begin() 5;
работает только для итераторов произвольного доступа, к которым итераторы std::set
не относятся.
Для итераторов ввода есть функция std::advance
:
set<int>::iterator it = myset.begin();
std::advance(it, 5); // now it is advanced by five
В C 11 также std::next
есть аналогичный, но не изменяющий его аргумент:
auto it = std::next(myset.begin(), 5);
std::next
требуется прямой итератор. Но поскольку std::set<int>::iterator
это двунаправленный итератор, оба advance
и next
будут работать.
Комментарии:
1. @»R. Martinho Fernandes» разве эти методы не имеют линейной временной сложности? Мне интересно, есть ли какой-то метод, который работает в логритмическое время, потому что множества, в конце концов, являются сбалансированными двоичными деревьями?
Ответ №2:
Оператор не определяет для этой структуры и имеет смысл только для итераторов произвольного доступа.
Первое решение: вы можете использовать std::advance , функция многократно использует оператор увеличения или уменьшения (operator или operator— ), пока не будут расширены n элементов.
set<int>::iterator it = myset.begin();
std::advance(it, 5);
std::out << *it << std::endl; // == it 5
Второе решение:
Используйте функции std::next или std::prev, производительность такая же, как у старой, потому что многократно использует оператор увеличения или уменьшения (operator или operator— ), пока не будет продвинуто n элементов.
Примечание: Если это итератор произвольного доступа, функция использует только один раз operator или operator- .
set<int>::iterator it1 = myset.begin();
std::next(it1, 5); // == it1 5
std::out << *it1 << std::endl; // == it1 5
set<int>::iterator it2 = myset.end();
std::prev(it2, 5); // == it2 - 5
std::out << *it2 << std::endl; // == it2 - 5
Примечание: Если вы хотите получить доступ, векторы очень эффективны для доступа к его элементам (как и массивы) и относительно эффективно добавляют или удаляют элементы с его конца.
Ответ №3:
Получить элемент по индексу из C 11 std::set
std::set
в C нет средства получения по индексу, поэтому вам придется создавать свой собственный, самостоятельно повторяя список и копируя его в массив, а затем индексируя его.
Например:
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> uniqueItems; //instantiate a new empty set of integers
uniqueItems.insert(10);
uniqueItems.insert(20); //insert three values into the set
uniqueItems.insert(30);
int myarray[uniqueItems.size()]; //create an int array of same size as the
//set<int> to accomodate elements
int i = 0;
for (const int amp;num : uniqueItems){ //iterate over the set
myarray[i] = num; //assign it to the appropriate array
i ; //element and increment
}
cout << myarray[0] << endl; //get index at zero, prints 10
cout << myarray[1] << endl; //get index at one, prints 20
cout << myarray[2] << endl; //get index at two, prints 30
}
Или удобная функция dandy для пошагового выполнения, а затем вернуть правильный:
int getSetAtIndex(set<int> myset, int index){
int i = 0;
for (const int amp;num : myset){ //iterate over the set
if (i == index){
return num;
}
}
string msg = "index " to_string(index)
"is out of range";
cout << msg;
exit(8);
}
int main(){
set<int> uniqueItems; //instantiate a new empty set of integers
uniqueItems.insert(10);
uniqueItems.insert(20); //insert three values into the set
uniqueItems.insert(30);
cout << getSetAtIndex(uniqueItems, 1);
}