Обратная итерация с использованием прямого итератора

#c #iterator #set

#c #итератор #установить

Вопрос:

У меня есть функциональность, в которой я хочу сравнить каждый элемент набора с предыдущими элементами. Я хочу сделать что-то вроде этого:

     std::set<int> sSet;
    std::set<int>::iterator it;
    std::set<int>::iterator itR;

    sSet.insert(1);
    sSet.insert(2);
    sSet.insert(3);
    sSet.insert(4);
    sSet.insert(5);
    sSet.insert(6);

    for (it=sSet.begin(); it!=sSet.end();   it)  //simple forward loop
    {
      itR = it;
      if(it != sSet.begin())  
        itR--;
      for(;itR!=sSet.begin();itR--)
      {
        //Reverse iteration
        //for comparing every element to all the previous elements
        //Problem here is it goes up to the second element only and not first 
        //because of the condition itR!=sSet.begin()
      } 
    }     
 

Я думал об использовании обратных итераторов здесь, но опять же я не смог найти способ установить обратный итератор из определенной позиции (или прямого итератора).

Есть ли какой-нибудь правильный способ сделать это?

Обновление: набор, используемый выше, предназначен только для демонстрации. Фактическая реализация как набор класса и определяется следующим образом:

     std::set<TBigClass, TBigClassComparer> sSet;
    class TBigClassComparer
    {
     public:
     bool operator()(const TBigClass s1, const TBigClass s2) const
     {
       //comparison logic goes here
     }
    };
 

Ответ №1:

Хотите обратного ?! Используйте обратный итератор:

 std::set<int> sSet;
    std::set<int>::iterator it;
    std::reverse_iterator<std::set<int>::iterator> itR;

sSet.insert(1);
sSet.insert(2);
sSet.insert(3);
sSet.insert(4);
sSet.insert(5);
sSet.insert(6);

for (it=sSet.begin(); it!=sSet.rend();   it)  //simple forward loop
{
  itR = std::reverse_iterator<std::set<int>::iterator>(it);
  for(;itR!=sSet.rbegin();  itR)
  {
    //Reverse iteration
    //for comparing every element to all the previous elements
    //Problem here is it goes up to the second element only and not first 
    //because of the condition itR!=sSet.begin()
  } 
}     
 

Обратите внимание, однако, что когда итератор отменяется, перевернутая версия указывает не на тот же элемент в диапазоне, а на предшествующий ему. Это сделано для того, чтобы упорядочить конечный элемент диапазона: итератор, указывающий на конечный элемент диапазона, при обратном изменении изменяется на указатель на последний элемент (не за ним) диапазона (это будет первыйэлемент диапазона, если наоборот). И если итератор для первого элемента в диапазоне отменяется, обратный итератор указывает на элемент перед первым элементом (это был бы конечный элемент диапазона, если перевернутый).

Комментарии:

1. itR = it; Это недопустимое присвоение

2. @skmic, да, спасибо. Я отредактировал ответ — я изменил способ использования reverse_iterator

3. Спасибо за объяснение. Где вы инициализировали itR? Я предполагаю, что вы хотели удалить эту строку ‘itR = it;’, поскольку это привело бы к ошибке компиляции. Таким образом, itR теперь является нулевым ptr.

4. @skmic Я исправил это с помощью оператора присваивания

5. @spineight Еще одно исправление, внутренний цикл for должен иметь условие itR != sSet.rend(), а не sSet.rbegin(), поскольку мы выполняем обратный переход, и это условие if(it != sSet.begin()) itR; больше не требуется. Ваше решение работает :).

Ответ №2:

Вы можете использовать внутренний цикл while:

 while (true)
{
    // do your comparison here

    if (itR == sSet.begin())
        break;

    --itR;
}