Получить элемент из произвольного индекса в наборе

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