Предположим, у вас есть плоская таблица, в которой хранится иерархия упорядоченного дерева:
Id Name ParentId Order
1 'Node 1' 0 10
2 'Node 1.1' 1 10
3 'Node 2' 0 20
4 'Node 1.1.1' 2 10
5 'Node 2.1' 3 10
6 'Node 1.2' 1 20
Вот диаграмма, где мы имеем [id] Name
. Корневой узел 0 вымышленный.
[0] ROOT
/ \
[1] Node 1 [3] Node 2
/ \ \
[2] Node 1.1 [6] Node 1.2 [5] Node 2.1
/
[4] Node 1.1.1
Какой минималистичный подход вы бы использовали для вывода этого в HTML (или текст, если на то пошло) как правильно упорядоченное, правильно отступающее дерево?
Предположим, что у вас есть только базовые структуры данных (массивы и хеш-карты), нет причудливых объектов со ссылками родитель / потомок, нет ORM, нет фреймворка, только две ваши руки. Таблица представлена в виде набора результатов, к которому можно получить произвольный доступ.
Псевдокод или простой английский в порядке, это чисто концептуальный вопрос.
Бонусный вопрос: существует ли принципиально лучший способ хранения древовидной структуры, подобной этой, в СУБД?
ИЗМЕНЕНИЯ И ДОПОЛНЕНИЯ
Чтобы ответить на вопрос одного комментатора ( Mark Bessey ): корневой узел не нужен, потому что он все равно никогда не будет отображаться. ParentId = 0 - это соглашение для выражения "это верхний уровень". Столбец «Порядок» определяет порядок сортировки узлов с одним и тем же родителем.
«Результирующий набор», о котором я говорил, может быть изображен как массив хеш-карт (чтобы остаться в этой терминологии). Для моего примера должно было быть уже там. Некоторые ответы проходят лишнюю милю и сначала ее строят, но это нормально.
Дерево может быть сколь угодно глубоким. Каждый узел может иметь N детей. Однако я не имел в виду дерево «миллионов записей».
Не путайте мой выбор имен узлов ('Node 1.1.1') с тем, на что можно положиться. С таким же успехом узлы можно было бы назвать «Фрэнк» или «Боб», структура имен не подразумевается, это просто для того, чтобы сделать их читаемыми.
Я опубликовал свое собственное решение, чтобы вы, ребята, могли разобрать его на куски.