Покончить с Globals?

У меня есть набор древовидных объектов с глубиной где-то в 20-е годы. Каждому из узлов в этом дереве необходим доступ к корню своего дерева.

Пара решений:

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

Может ли кто-нибудь предоставить дизайн, который не использует глобальный (в любом варианте), но более эффективен, чем №1 или №2 как в памяти, так и в циклах соответственно?

Редактировать: Поскольку у меня есть набор деревьев, я не могу просто сохранить его в статике, так как было бы трудно различать деревья. (спасибо Maccullt)

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

maccullt 16.09.2008 04:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
1
407
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Передайте корень в качестве параметра тем функциям в узле, которым он нужен.

Обновлено: параметры действительно следующие:

  1. Сохраните корневую ссылку в узле
  2. Не храните корневую ссылку вообще
  3. Сохраните корневую ссылку в глобальном
  4. Сохраните корневую ссылку в стеке (мое предложение, либо шаблон посетителя, либо рекурсивный)

Думаю, это все возможности, варианта 5 нет.

Аля Visitor выкройка аккуратная. Я не думал об этом.

Allain Lalonde 16.09.2008 04:21

В find это может быть очень болезненным, когда что-то меняется, особенно когда стеки вызовов становятся глубже.

Jonathan Allen 16.09.2008 04:26

Я не интерпретировал это как рекурсивный. У меня мог бы быть фрагмент кода, который проходит по дереву и выполняется на каждом узле. В этом коде будет ссылка на корень.

Allain Lalonde 16.09.2008 04:28

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

Вы идете на компромисс: ясность кода и меньше проблем с производительностью в будущем. Это означает, что «пока не оптимизируйте». Поскольку вы находитесь на этапе оптимизации, иногда необходимо отказаться от некоторых удобочитаемости и хороших методов программирования в пользу производительности. Я имею в виду, что побитовые хаки не читаются, но они быстрые.

Я не уверен, сколько у вас есть древовидных объектов, но лично я бы выбрал первый вариант. Если вы не имеете дело с тысячами + деревьев, указатели на самом деле не будут содержать намного больше, чем несколько строк. Если память действительно является очень важной проблемой, попробуйте оба метода (они кажутся довольно простыми в реализации) и запустите их через профилировщик. Или используйте отличный Обозреватель процессов.

Обновлено: одно из приложений, над которыми я работаю, имеет дерево узлов, содержащее около 55 тыс. Узлов. Мы строим древовидную структуру, но также поддерживаем массив для поиска O (1). Намного лучше, чем O (m * n), которое мы получали при использовании рекурсивного метода FindNodeByID.

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

Mike Stone 16.09.2008 04:31

Не напрягая, просто любопытно. Я подумал, что это интересный вопрос.

Allain Lalonde 16.09.2008 04:38

80K - это тривиально, если до этого дойти. Когда я впервые увидел код, я был очень "бестолковым", пока не прогнал его через профилировщик и не понял, что наши выделения String были примерно в 400 раз больше.

David J. Sokol 16.09.2008 05:11

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

Я настоятельно рекомендую вам выбрать №2. Всякий раз, когда вы сохраняете что-то, что могли бы вместо этого вычислить, вы делаете кеширование. В некоторых случаях кеширование - хорошая идея, но это еще и головная боль при обслуживании. (Например, что, если вы переместите узел из одного дерева в другое, изменив его родительский элемент, но забудете также обновить корневое поле?) Не кэшируйте, если вам это не нужно.

Вы можете унаследовать класс от TreeView, а затем добавить одноэлементное статическое свойство. Таким образом, вы эффективно добавляете глобальное поле, которое ссылается на единственный экземпляр класса, но имеет то преимущество, что пространство имен ограничено этим классом.

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

Это может оказаться таким же, как №1, в зависимости от того, как Java связывает узлы с их родителями. (Я не уверен, и мне придется это профилировать)

Я почти уверен, что это будет то же самое, что и №1, на самом деле нет другого способа реализовать это.

Niall 16.09.2008 04:42

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

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