Я хотел бы создать класс "сжатый массив" / "сжатый вектор" (подробнее см. ниже), который позволяет получить доступ к случайным данным с более или менее постоянным временем.
"более или менее постоянное время" означает, что хотя время доступа к элементу не является постоянным, оно не должно увеличиваться, когда я приближаюсь к определенной точке массива. То есть контейнер не должен делать значительно больше вычислений (например, "распаковать все еще раз, чтобы получить последний элемент" и "почти ничего не делать, чтобы получить первый" ), чтобы получить один элемент. Вероятно, это может быть достигнуто путем разделения массива на куски сжатых данных. То есть доступ к одному элементу должен принимать "среднее время" + - некоторое отклонение. Я могу сказать, что я хочу, чтобы время доступа к лучшему и время доступа наихудшего случая были относительно близки к среднему времени доступа.
Каковы мои варианты (подходящие алгоритмы/уже имеющиеся контейнеры - если они есть)?
Детали контейнера:
- Контейнер действует как линейный массив идентичных элементов (например, std::vector)
- После инициализации контейнера данные постоянны и никогда не изменяются. Контейнер должен предоставлять доступ только для чтения.
- Контейнер должен вести себя как массив / std::vector - то есть значения, доступные через оператор [], есть .size() и т.д.
- Было бы неплохо, если бы я мог сделать это как класс шаблона.
- Доступ к данным должен быть более или менее постоянным. Мне не нужно одинаковое время доступа для каждого элемента, но мне не нужно распаковывать все, чтобы получить последний элемент.
Пример использования:
Двоичный поиск по данным.
Детали данных:
1. Данные представляют собой структуры, состоящие в основном из поплавков и нескольких ints. Есть больше плавающих, чем ints. Нет строк.
2. Маловероятно, что в массиве много одинаковых элементов, поэтому просто индексировать данные не удастся.
3. Размер одного элемента меньше 100 байт.
4. Общий размер данных на один контейнер составляет несколько килобайт и несколько мегабайт.
5. Данные не разрежены - это непрерывный блок элементов, все они назначены, нет "пустых слотов".
Цель сжатия заключается в уменьшении количества блоков, которые требуется блоку по сравнению с несжатым представлением в виде массива, сохраняя при этом некоторую разумную производительность доступа к чтению и позволяя случайным образом обращаться к элементам как к массиву. То есть данные должны храниться в сжатой форме, и я должен иметь доступ к ней (только для чтения), как если бы это был std::vector или аналогичный контейнер.
Идеи/мнение?