2012-02-25 2 views
1

Я ищу структуру данных, похожую на T[,,] (трехмерный массив), за исключением того, что заранее не знаю размеров (и не имеет разумной верхней границы), которые со временем будут расширяться наружу. Я также хотел бы использовать отрицательные индексы.Структура данных для расширяемой трехмерной матрицы?

Единственное, что приходит на ум, это словарь, с каким-то свойством Point3 struct. Есть ли другие альтернативы? Я бы хотел, чтобы поиски были как можно быстрее. Данные всегда будут группироваться вокруг 0,0,0. Он может расширяться в любом направлении, но между точками никогда не будет «пробелов».


Я думаю, что я собираюсь идти вперед и просто использовать Dictionary<Point3, T> сейчас, и посмотреть, как это работает. Если это проблема с производительностью, я попытаюсь создать обертку вокруг T[,,], чтобы использовать отрицательные индексы.

+0

Вы просите N-мерный массив (который вы не знаете размеры до времени исполнения)? Что вы планируете делать с этим массивом? Что заставляет вас полагать, что массив является правильной структурой данных для вашей проблемы? –

+0

@ProgrammingHero: Специально 3-мерный. Я думал о массиве, потому что быстрое время поиска имеет решающее значение. Теперь, когда я думаю об этом больше, я думаю, что мне придется в конечном итоге выгрузить данные (он станет слишком большим), поэтому «центр» данных может сдвинуться с 0,0,0. Это для игры, и ее можно назвать тысячами или миллионами раз в секунду. – mpen

+0

Можете ли вы рассказать немного больше о контексте вашей проблемы? Также существуют ли какие-либо нестандартные операции, которые необходимо поддерживать, т. Е. Запросы диапазона? –

ответ

1

Я вроде как предполагаю, что вам нужен динамический аспект, потому что массив может быть огромным. В этом случае вы можете попытаться выделить ваш массив как набор 3d 'плиток'. На верхнем уровне у вас есть трехмерная структура данных, в которой хранятся указатели на ваши плитки. Вы расширяете и распределяете это по мере продвижения.

Каждая отдельная плитка может содержать, скажем, 32x32x32 вокселей. Или любая сумма соответствует вашим целям. Поднимая вас, плитка выполняется путем деления индекса вашей координаты на 32 (по битам, конечно,), а индекс в плитке рассчитывается путем маскировки верхних бит.

Подобный поиск довольно дешев, возможен на одном уровне с .net Dictionary, но он будет использовать меньше памяти, что тоже хорошо для производительности.

Результирующий массив будет коротким: границы массива кратны размеру вашей плитки.

+0

Именно это я и делаю. Я тайно спрашивал, как я должен хранить куски плиток; сами «плитки» будут всего лишь 32x32x32 массивов. то есть, какую структуру данных я держу в указателях? – mpen

+0

Ну, я думаю, великие мысли думают одинаково. Но в любом случае, сколько плиток вам нужно? Тысячи? Вы можете использовать традиционный массив для хранения фрагментов и при необходимости скопировать его в больший массив. Даже если у вас есть миллионы плиток, копирование в большой массив должно быть довольно быстрым. Я не думаю, что вам нужно сделать это для каждого кадра .... –

+0

У меня есть рендеринг с почти миллионными плитами, но он становится лагги. Чем больше я могу поддержать, тем лучше. Я мог бы попытаться создать обертку вокруг традиционного массива, чтобы я мог получить доступ к ней с отрицательными индексами ... но сначала попробую диктофон и посмотрю, как это работает. – mpen

2

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

Я собираюсь немного сумасшедший здесь, но я думаю, что ваши индексы должны быть в Spherical Coordinates. Это имеет смысл для меня, поскольку ваши данные растут наружу. Это также упростит поиск элементов в определенном диапазоне от (0, 0, 0).

+0

Раньше я использовал полярные координаты, но я никогда не думал о распространении этого на 3D. Я не думаю, что это будет работать очень хорошо, потому что мои данные слишком «блочные»; т. е. длины и углы не так хорошо работают с целыми координатами. – mpen

+0

Хммм, вы можете преобразовать их в целые углы и длины. Тем не менее, вы получите сферические блоки. Я не думаю, что преобразование будет слишком болезненным - конечно, меньше, чем O (logn) добавления узла в сбалансированное KD-дерево. – zmbq

+0

Хорошо, скажем, блок справа от меня равен (1,0,0), где «1» - длина вектора, а (0,0) - два угла. Тогда какой будет блок по диагонали передо мной? Это расстояние sqrt (2) и 45 градусов на одном из углов. Как вы представляете это как целое число? Я * мог * использовать поплавки и округлять его, но я подозреваю, что некоторые блоки будут пропущены полностью, особенно когда они будут дальше. – mpen

2

Если вам могут потребоваться запросы диапазона, KD-Trees приходит на ум. Они представляют собой древовидные структуры, на каждом уровне разделяют вселенную на две по одной оси. Они предлагают время поиска O (logN) (для постоянного количества измерений), которое может быть или не быть достаточно быстрым, но они также обеспечивают время O (logN + S) для запросов диапазона, где S - размер найденных элементов, что обычно очень хорошо. Они могут обрабатывать динамические данные (вставки и удаления вместе с поиском), но в результате дерево может стать неуравновешенным. Также вы можете выполнить поиск ближайших соседей по заданной точке (т. Е. Получить 10 ближайших объектов (7,8,9)). Википедия, как всегда, является хорошей отправной точкой: http://en.wikipedia.org/wiki/Kd-tree

Если есть огромные числа вещей в мире, если мир очень динамичен (вещи движутся, создаются/уничтожаются все время), kd-деревья могут быть недостаточно хорошими. Если в большинстве случаев вы только попросите «дать мне дело в (7,8,9)», вы можете использовать хеш, как вы упомянули в своем вопросе, или что-то вроде List<List<List<T>>>. Я бы просто реализовал в зависимости от того, что проще в интерфейсе, и беспокоиться о производительности позже.

+0

Я думаю, что KD-дерево будет слишком медленным. Сначала я начну с словаря, потому что это легко. – mpen

1

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

Если вы хотите сохранить куски вокруг игрока, вам может понадобиться структура массива «текущий мир» вокруг игрока, так что это трехмерный массив с центральным куском на 9,9,9 с размером от [20,20,20]. Каждый раз, когда игрок покидает центральный кусок для другого, вы повторно индексируете массив, чтобы удалить старые куски и двигаться дальше.

В конечном счете, вы запрашиваете варианты оптимизации игрового движка, но почти невозможно сказать, что будет правильным для вас. Несмотря на то, что игры, как правило, более оптимизированы для производительности, чем другие приложения, не заманиваются в микро-оптимизации; оптимизируйте для читаемость, а затем оптимизируйте ее, если найдете нужным.

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

+0

Я знаю проблемы преждевременной оптимизации, но у меня уже есть что-то работает, и я уже нажимаю max, и я едва реализовал какие-либо функции. Повторная индексация массива звучит дорого. Разве было бы лучше создать обертку вокруг «T [,,]», чтобы центр мог прозрачно перемещаться? то есть, «0,0,0» может не отображаться на «T [0,0,0]», а какой-либо другой индекс, в зависимости от того, где находится центр? Тогда я могу выделить гораздо больший массив, скажем 100x100x100, и сосредоточить его около 50,50,50 и, возможно, использовать только 10x10x10, но мне не придется переиндексации, пока он не сдвинется с края ... – mpen

+1

Вот почему это вызов только у вас есть информация, чтобы сделать; если вы повторно индексируете каждый раз, когда центр изменяется, вам нужно обновлять 8000 ссылок каждый раз при возникновении этого события. Если вы проходите через абстракцию, вы должны применять преобразование координат каждый раз, когда вы выполняете поиск в матрице. Я не могу сказать вам, что будет быстрее, не зная вашего двигателя так же хорошо, как и вы; даже тогда я хотел бы сравнить оба варианта. –

+0

Стоит добавить: Ваша проблема может заключаться в том, что вы делаете много прямых поисков. Рассматривали ли вы способы сокращения числа? –