Мне нужно найти индекс элемента в std :: set. Этот индекс может быть визуализирован как расстояние итератора от начала.
Одним из способов может быть:
for(int i = 0, set<int>::iterator it = s.begin(); it != iteratorToBeFound; ++it, ++i);
Это явно занимает O (N) время. Но мы знаем, что расстояние от корня в бинарном дереве поиска, реализованное внутренним заданием, может быть найдено за O (log n).
Есть ли какой-либо способ реализовать то же самое, чтобы найти индекс за время O (log n) в наборе C ++?
Вы можете использовать отсортированный std::vector<int>
, Если это отсортировано, вы можете найти элемент в O(log n)
, И вы можете найти расстояние в постоянном времени O(1)
,
Под отсортированным вектором я подразумеваю, что после каждой вставки (или после множества вставок) вы делаете std::sort(v.begin(), v.end());
Если ваш тип внутри std::set<T>
не такой легкий как int
— вы можете сохранить оба — std::set<T>
и отсортированный вектор итераторов std::vector<std::set<T>::iterator>
, Но было бы несложно поддерживать синхронизацию этих структур. Может быть, вы можете добавить какую-то похожую позицию T
? Или держать std::set<std::pair<T,int>, comp_first_of_pair<T>>
где comp_first_of_pair
это просто иметь set
отсортировано только по T
а второй int
для сохранения позиции в наборе?
Всего несколько идей — чтобы иметь даже O(1)
расстояние время …
Вы можете использовать функцию std::set<>::find
искать элемент x
и вычислить расстояние до первого итератора множества.
std::distance(s.begin(), s.find(x))
Однако, как показывают комментарии, время выполнения расстояния зависит от типа используемого итератора. В случае множества это двунаправленный итератор, а расстояние равно O (n).
Вы не можете использовать математику с двунаправленными итераторами. Так что единственный приемлемый способ — это посчитать самостоятельно (сколько ИНТ меньше X вы вставили в набор).
Но если вы четко разделили этапы «сбора данных» и «использования данных» — возможно, стоит заменить станд :: набор с отсортированным станд :: вектор. Его сложнее поддерживать, но у него есть свои преимущества, включая математику итератора (так что вы можете получить поиск с помощью O (log n) с помощью станд :: binary_search и расстояние с O (1))
Если вычисление индекса действительно Ваше узкое место, тогда я вижу 2 варианта:
std::map
,std::vector
, Это не так плохо, как может показаться на первый взгляд.set
,set
,boost:shared_ptr
или же std::unique_ptr
[только c ++ 11])std::lower_bound
, insert( lower_bound(b,e,x), x )