Структура данных / Алгоритм управления неперекрывающимися диапазонами значений?

Я работаю над системой, которая имеет 10 тысяч флагов для пользователя. Все флаги являются последовательными по номерам, от 0 до X, независимо от того, что X заканчивается. Ожидается, что Х будет расти со временем. И мы ожидаем, что будет много-много пользователей.

Наши основные проблемы:

  1. Возможность быстро проверить, установил ли пользователь какой-либо данный флаг.
  2. Возможность быстро установить флаг.
  3. Возможность оптимизировать хранилище данных до минимально возможного размера.

С флагами 10 КБ мы смотрим около 1 КБ данных на пользователя в памяти, если мы используем битовый вектор. Что может быть слишком много. И что еще хуже, это в Javascript, хранящемся в базе данных документов, сериализованной в JSON, что означает, что у нас есть несколько вариантов хранения, ни один из которых мне особенно не нравится.

  1. Сохраняйте флаги как вывод JSON объекта Uint32Array. Похоже: "{"0":10,"1":4294967295}", К сожалению, в среднем требуется 17 байт на 4 байта, которые хранятся, когда флаги приближаются к заполненному состоянию, что в 4 раза больше памяти и приводит к 5 Кб памяти при сериализации. Это не идеально.
  2. Выполните нашу собственную сериализацию JSON, используя base64, чтобы избежать раздутых размеров подхода числа-как-строки. К сожалению, это добавляет дополнительный этап обработки к фазам ввода / вывода JSON, что усложняет ситуацию, потому что теперь мы должны изменить наши данные во время процесса и замедлить все.

Итак... ненадолго отложим идею битвектора. Мне было интересно, если есть, возможно, лучший подход. Я подумал об использовании "массива диапазонов", что-то вроде:

[{"m":0,"x":100},{"m":102},{"m":108,"x":204}]

Мы можем сделать несколько предположений относительно данных в этой системе, что и привело меня к такому подходу:

  1. Флаги никогда не устанавливаются. Как только это установлено, это останется установленным.
  2. Флаги, как правило, сгруппированы. Если установлен флаг X, существует большая вероятность того, что X-1 и X+1 также будут установлены.
  3. Флаги обычно устанавливаются при увеличении значений индекса. Если установлен флаг X, то X-1 с большей вероятностью будет установлен, чем X+1, а X+1, вероятно, будет установлен довольно скоро после этого.

Поэтому из-за этих условий я думаю, что хранение массива объектов диапазона может быть оптимальным решением. Таким образом, со временем флаги пользователя в конечном итоге сливаются в одну запись с большим диапазоном. Оптимальный случай конечно:

[{"m":0,"x":10000}]

Конечно, наихудший сценарий - если им каким-то образом удается оказаться в состоянии, в котором они устанавливают все остальные флаги.

[{"m":0},{"m":2},{"m":4},{"m":6},{"m":8},{"m":10}...{"m":10000}]

Это было бы плохо. Я думаю, что это намного хуже, чем решение bitvector. Но мы уверены, что этого не произойдет.

Итак, что касается возможности быстро решить, установлен ли флаг; это просто O(logn) бинарный поиск (так как массив будет отсортирован); просто найдите объект диапазона, ближайший к вашему номеру, проверьте, находится ли ваш номер в этом диапазоне, и вернитесь.

Вставки более хитры. Это все еще будет бинарный поиск, но теперь мы модифицируем массив.

  1. одна соседняя вставка родного брата: оптимальный сценарий. Мы находим диапазон, где минимальное или максимальное значение равно единице от числа, которое мы вставляем, и просто уменьшаем или увеличиваем значение текущего диапазона. O(1)
  2. Не вставлять соседних братьев и сестер: просто вставьте новый узел с установленным значением min. O(n), потому что мы будем перемещать все после него в массиве вниз.
  3. Вставьте двух соседних братьев и сестер: измените значение max на максимальное значение правого диапазона братьев и сестер, удалите диапазон правых братьев и сестер из массива и сдвиньте все после него влево. На).

Поэтому случаи 2+3 заставляют меня задуматься, не стоит ли мне пытаться использовать какое-то сбалансированное двоичное дерево поиска для этого. Красно-черное дерево, например.

Это стоит беспокоиться? Я обдумываю это?

0 ответов

Другие вопросы по тегам