Блог пользователя lazybones

Автор lazybones, история, 6 лет назад, По-русски

Задача: Вывести каждый k-элемент set, начиная с какого-то. Если начинать с начала, то всё хорошо:

#include <bits/stdc++.h>

using namespace std;

int main()
{

    set <int> a;
    for (int i = 1; i<=10; i++)
    {
        a.insert(i);
    }

    /**< Выводим все значения на нечётных позициях, начиная с первого элемента */
    for (auto it = a.begin(); it != a.end(); advance(it, 2))
    {
        cout << *it << ' ';
    }
    cout<<endl;

}

Если сдвигаю вывод, то вывод зацикливается при некоторых позициях сдвига и размере сдвига.

ЭТО ПОВИСНЕТ:

#include <bits/stdc++.h>

using namespace std;

int main()
{

    set <int> a;
    for (int i = 1; i<=10; i++)
    {
        a.insert(i);
    }

    /**< Если нужно начинать не с первого то */
    auto it = a.begin();
    advance(it, 1);
    for (it ; it != a.end(); advance(it, 2))
    {
        cout << *it << ' ';
    }
}

Я так понимаю программа зацикливается из-за того, что итератор никогда не становится равным a.end(), у кого есть знания, как такое можно записать правильно?

Единственное, что смог придумать — завел переменную, в которой держал "текущий номер" элемента set.

#include <bits/stdc++.h>

using namespace std;

int main()
{

    set <int> a;
    for (int i = 1; i<=10; i++)
    {
        a.insert(i);
    }

    /**< Если нужно начинать не с первого, то */
    auto it = a.begin();
    advance(it, 1);
    int i = 1;
    for (it ; it != a.end(); advance(it, 2))
    {
        i +=2;
        if (i>a.size())
        {
            break;
        }
        cout << *it << ' ';

    }

}

Теги set
  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
6 лет назад, # |
Rev. 2   Проголосовать: нравится +16 Проголосовать: не нравится

Первое, что приходит в голову — написать свою функцию my_advance, третий аргумент которой — итератор, до которого нужно идти (то есть в данном случае — a.end()). Получилось так:

Код
  • »
    »
    6 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +1 Проголосовать: не нравится

    Почему тогда не просто:

        auto it = a.begin();
        int i;
        for (i = 0; it != a.end(); it++, i++)
            if (i%2==1) cout << *it << ' ';
    
    • »
      »
      »
      6 лет назад, # ^ |
      Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

      Вообще есть много способов, один из которых я привёл, но я не исключаю существование других.

      Конкретно Ваш код, видимо, нельзя использовать, если, например, нужно начинать с элемента, индекс которого больше или равен расстоянию между элементами, которые нужно выводить, например: 10, 12, 14, 16, .... UPD. Как написано ниже, с небольшим изменением можно.

      • »
        »
        »
        »
        6 лет назад, # ^ |
        Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

        Суть в том что итерировать сет можно только последовательно, как делать фильтрацию не имеет значения. Как мне кажется в вашем коде слишком много абстракций. В моем случае начальный элемент можно добавить одним условием i>start или проитерировать первые start элементов отдельным циклом. Код без внешней функции читается проще и понятен сходу. Без необходимости разбираться что значит my_advance.

        • »
          »
          »
          »
          »
          6 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          Да, тут Вы, наверно, правы. Но всё же мой код можно один раз написать, как шаблон, и дальше пользоваться. Хотя на асимптотику это действительно не влияет.

    • »
      »
      »
      6 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Я не думаю, что этот код отвечает на вопрос, попробуйте сами вывести каждый 3 начиная с 4. Но за ответ спасибо.

      • »
        »
        »
        »
        6 лет назад, # ^ |
          Проголосовать: нравится +6 Проголосовать: не нравится
        Я бы не мудрил и решал влоб

        Если цель — решить задачу, чтобы решение надежно работало.