Задать вопрос
@1eg10n

Как «выпрямить» кольцевой буфер c ограниченной доп.памятью?

Добрый день!

Не подскажете: функцию, алгоритм или переформулировку
Необходимо "выпрямить" кольцевой буфер c ограниченной доп.памятью.
Доступ к элементу кольцевого буфера O(1).
Размерность буфера до 0x10000.

Упрощенный пример: Буфер (5, 6, 7, 1, 2, 3, 4). Доп. памяти есть под 2 элемента.
P.S. На случай алгоритмов сортировок - в нем не хранятся последовательные числа.
  • Вопрос задан
  • 127 просмотров
Подписаться 1 Средний 10 комментариев
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Ваша задача - сделать циклический сдвиг массива на k позиций влево на месте, с O(1) дополнительной памяти.
Вот код:
void ShiftLeft(std::vector<int> &a, int k) {
  int n = a.size();
  int cycles = std::gcd(n, k);
  for (int start = 0; start < cycles; ++start) {
    int tmp = a[start];
    int i = start;
    while (true) {
      int next = i + k;
      if (next >= n) next -= n;
      if (next == start) break;
      a[i] = a[next];
      i = next;
    }
    a[i] = tmp;
  }
}


Работает это так: на место элемента вставет элемент на k позиций правее. Возьмем первый элемент, запомним его в tmp, поставим на его место тот, кто там должен быть. Освободилось место, поставим на него опять того, кто там должен быть и так далее. Рано или поздно мы вернемся к первому элементу. Но там уже стоит второй. Тут можно выйти из цикла и поставить на нужное место тот, кого мы сохранили в tmp. Но мы могли обойти не весь массив, как, например в случае n=6, k=2. Начав с 0 мы тут подвинем элементы 0,2,4, но не 1,3,5. Всего будет циклов gcd(n, k), и они все идут со сдвигом 1. Поэтому можно начинать с каждого из нескольких первых элементов.

Додуматься до этого можно так: сдвиг на 1 позицию понятно как циклом while сделать-то и одной переменной tmp. А на несколько? Надо только заметить что элементы разбиваются на циклы.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
mayton2019
@mayton2019
Bigdata Engineer
Автор мне кажется ты решаешь две разных задачи.
Первое - кольцевой буфер. Его не надо сортировать и его API
обычно очень простой. Это блокирующие push/pop или там атомарный
peek или проверка на пустоту. Они работают быстро и в этом их преимущество.

Если ты задумал очереди с приоритетами то посмотри например пирамиду (heap).
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы