BitSegmentedArray

Мне предоставили реализовать класс, который наследует SegmentedArray и характеризуется следующим:

  • принимает большой массив
  • элементы массива — 0 и 1
  • частые запросы get() и set()

Чтобы была возможность хранить очень большой массив, я решила построить класс с помощью битовых операций. Это было возможно, так как элемент моего массива — это 0 и 1, и любое число можно представить в виде последовательности нулей и единиц. Поэтому внутри класса если массив long, в одной ячейке которого может храниться до 64 элементов. Так была решена проблема с расходом памяти.

Из-за представления чисел в двоичном коде, к ним легко применимы битовые операции. Например, для реализации метода get() достаточно использовать битовый сдвиг и битовое «и». Следовательно, метод работает за О(1).

В реализации метода set() мне помогла блочная структура (64 элемента в 1 ячейке массива). А именно: я проверяю границы заданного отрезка, а ячейки, которые попали внутрь полностью просто приравниваю константе: 0 — если все элементы ячейки нули, -1 — если все элементы ячейки единицы.

Точно так же реализован метод add().

С методом min() всё и того проще: ответом служит либо 0, либо 1. Первый же ноль, встреченный на заданном отрезке, определяет ответ.

Также я предположила, что, как и в большинстве олимпиадных задач, индексация массива начинается с единицы. То есть в методе get(), set(), add() и min() необходима сначала уменьшить каждый индекс на единицу, а лишь потом проводить операции над массивом, так как индексация в нём начинается с нуля.

Теоретическая оценка сложности методов:

  • get(i): O(1);
  • set(x, y, val): O((y-x)/64);
  • add(x, y, val): O((y-x)/64) — для val%2==1, и O(1) — для val%2==0;
  • min(x, y) — O((x-y)/64) — в худшем случае (на отрезке все элементы нули), O(1) — в лучшем случае (на отрезке все элементы единицы).

Код программы:

Протестировать программу можно здесь.

Простейшая реализация интерфейса: SimpleSegmentedArray.

Сравнение скорости работы методов:

4 thoughts on “BitSegmentedArray

  1. Хорошая реализация, вот некоторые замечания:
    1) почему это this.realSize = size/65 + 1; деление на 65? Как Вы в long вместите 65 бит?
    2) странный код вида

    разве это не

    3) укажите явно, что индексация начинается с единицы — вообще несколько сомнительное решение, в задании это не было указано. Сейчас из отчета это не видно, комментариев в коде тоже нет.

    Ну и неплохо было бы замерять производительность, сравнив с производительностью обычного массива на достаточно большом тесте (приближающимся к граничному размеру — но чтобы еще не было ошибки при выделении обычного массива из-за нехватки памяти). Также написать теоретическую оценку сложности основных операций над массивом.

  2. 1) Исправила.
    2) Исправила.
    3) Дописала.
    Теоретическая оценка добавлена.
    Производительность замерю до выходных.

  3. Производительность так и не замерили, но все равно, учитывая, что Ваша реализация была первой, поставлю полный балл (30 баллов). За замер производительности могу еще добавить баллов.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *