Какая структура данных будет эффективно хранить целочисленные диапазоны?

10

Мне нужно сохранить коллекцию целых чисел в диапазоне от 0 до 65535, чтобы я мог быстро сделать следующее:

  • Вставьте новое целое число
  • Вставьте диапазон смежных целых чисел
  • Удалить целое число
  • Удалить все целые числа ниже целого
  • Проверьте, присутствует ли целое число

У моих данных есть свойство часто содержать целые числа в коллекции. Например, коллекция может в один момент времени быть:

{ 121, 122, 123, 124, 3201, 3202, 5897, 8912, 8913, 8914, 18823, 18824, 40891 }

Самый простой подход - просто использовать сбалансированное бинарное дерево, такое как C ++ std :: set, однако, используя его, я не использую тот факт, что у меня часто бывают серии чисел. Возможно, было бы лучше хранить коллекцию диапазонов? Но это означает, что диапазон должен иметь возможность разбиваться, если целое число в его середине удаляется, или соединяться вместе, если заполнено пространство между двумя диапазонами.

Существуют ли какие-либо структуры данных, которые бы хорошо подходили для этой проблемы?

WilliamKF
источник

Ответы:

9

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

В этой структуре данных вы можете поддерживать все свои операции за времени, где - количество интервалов. Так как нам гарантировано , я ожидаю, что это будет весьма эффективно. (В частности, да, вы можете разбить интервал на две части или объединить два смежных интервала в один интервал за времени.)О(Л.Г.N)NN65535О(Л.Г.N)

DW
источник
5

Прежде всего, ваш вопрос сформулирован очень плохо, если по какой-либо другой причине, потому что «быстро» не значит много. Вы должны будете предоставить некоторую метрику того, что означает «быстрый».

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

  • Должны ли все эти операции быть одинаково быстрыми или более важными, чем другие?
  • Есть ли другие соображения?
  • Является ли память проблемой?
  • Является ли возможность выполнять вставки, удаления и поиска из нескольких потоков?
  • Направлена ​​ли рабочая нагрузка на вставку? Удаление? Глядя вверх?

Во-вторых, если ваша проблемная область действительно то это обсуждение кажется просто глупым. Действительно ли нужен умный, причудливый алгоритм ? Особенно, когда простой массив является отличным вариантом, охватывающим одиночные целочисленные операции в постоянном времени, операции диапазона в линейном времени и затраты на линейное пространство?[0,65535]

Чтобы немного больше поработать, вы можете сэкономить место, если это важно, за счет скорости, сохраняя данные в виде битов в 8192 целых числах. Хотя с концептуальной точки зрения операции с одним целым числом все еще будут иметь постоянное время, а операции с целочисленными значениями по-прежнему будут линейным временем, они будут медленнее.

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

Если это не ваша проблема, и есть другие соображения, которые вы не передали (например, возможно, домен на самом деле не и вы пытались упростить проблему, о которой вы спрашивали), тогда вам понадобится чтобы задать свой вопрос еще раз, на этот раз сообщая нам актуальную проблему.[0,65535]

Ник Бугалис
источник
3

Вы могли бы рассмотреть структуру данных Integer, такую ​​как дерево Ван Эмде Боаса . Целочисленная структура данных работает с фиксированной вселенной . Некоторые из упомянутых вами операций могут быть реализованы очень эффективно. В частности, вставка, удаление и запрос одного элемента выполняется в . Другие операции (массовая вставка / удаление) могут быть более дорогостоящими, однако, используя битовые трюки в дереве Ван Эмде Боаса, вы сможете получить ускорение в размере, примерно равном размеру слова в вашей системе.Uзнак равно{0,...,U-1}О(журналжурналU)

В зависимости от структуры ваших данных, может быть много умных альтернатив для хранения ваших данных.

A.Schulz
источник