Разделы публикаций

 
     
 

Построение дерева из списка ID-Parent

nectarin
217
    nectarin nectarin
Сергей NectarIn Новиков
Специализации: 1

Поскольку данная задача возникает у разработчиков довольно часто, хотел бы поделиться простым и эффективным решением. Всё, что нам потребуется — это исходный массив примерно такого вида:
$listIdParent = array(
  => array('parent' => 0),
  => array('parent' => 1),
  => array('parent' => 1),
  => array('parent' => 2),
  => array('parent' => 4)
);


Как нетрудно догадаться, ключи исходного списка являются ID, а поля parent содержат ссылки на родительский элемент в дереве. Элемент с parent, равным 0, является корневым. Такой элемент должен быть единственным в списке, и в целом дерево должно быть консистентным (не должно быть "битых" ссылок и рекурсивной вложенности) — и, пожалуй, это единственные ограничения. Таким образом, важной особенностью используемого метода является то, что элементы исходного списка могут идти в любом порядке, в отличие от известного способа с array_pop(), который требует, чтобы элементы были отсортированы по уровню (глубине вложенности).

Дерево строится следующей функцией:
/**
 * Построение дерева из списка ID-Parent.
 * 
 * @param array Исходный список.
 * @return array Дерево.
 */
function buildTree(array $listIdParent) {
  // Подготовка ID корневого узла.
  $rootId 0;
10   
11   // Обход списка и обработка узлов.
12   foreach ($listIdParent as $id => $node) {
13     if ($node['parent']) {
14       // Сохранение в родительском узле ссылки на текущий.
15       $listIdParent[$node['parent']]['sub'][$id] =& $listIdParent[$id];
16     } else {
17       // Сохранение ссылки на корневой элемент.
18       $rootId $id;
19     }
20   }
21   
22   // Возврат корневого узла, содержащего всё построенное дерево.
23   return array($rootId => $listIdParent[$rootId]);
24 }

Для повышения удобочитаемости в коде функции опущены необходимые проверки входного массива на корректность.

Результат работы функции выглядит так:
array(
  => array(
    'parent' => 0,
    'sub' => array(
      => array(
        'parent' => 1,
        'sub' => array(
          => array(
            'parent' => 2,
10             'sub' => array(
11               => array('parent' => 4)
12             )
13           )
14         )
15       ),
16       => array(
17         'parent' => 1
18       )
19     )
20   )
21 )

При сравнении с другими способами построения дерева из списка ID-Parent можно выделить следующие основные моменты:

  • отсутствие рекурсии; достаточно одной функции;

  • всего один цикл по исходному массиву для полного построения дерева;

  • все манипуляции с массивом заключаются в установке ссылок на дочерние элементы, что сильно экономит память и увеличивает быстродействие (по сравнению с методами, перемещающими сами элементы массива).


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

2
Просмотров: 574
     

Новости inPHP.org Новости inPHP.org
27.05.2010   Технические работы.
По техническим причинам возможны кратковременные перебои в работе сайта проекта в период с 27.05.2010 по 1.06.2010.
02.03.2010   Доступ участников к разработке тестирований.
В тестовом режиме запущен функционал, позволяющий участникам проекта разрабатывать собственные тестирования. Разработанные сообществом тестирования не имеют ограничений официальной аккредитации и в любое время доступны любому участнику.
19.02.2010   Введён общий рейтинг участника.
В рамках программы развития проекта введён параметр общего рейтинга участника. Соответствующие изменения внесены в правила проекта. Рейтинг - один из показателей, которые будут активно использоваться в готовящемся к запуску функционале. Первое из нововведений - доступ участников к системе разработки собственных тестирований и возможность неограниченного использования тестирований, разработанных сообществом, будет запущено в течение марта 2010 года.
 
Содействуют развитию Содействуют развитию
webdev
198
    webdev webdev
Константин
Специализации: 2
Участники проекта Участники проекта
necron
20
    necron necron

Специализации: 0
_iks_
60
    _iks_ _iks_

Специализации: 0
diaborn
60
    diaborn diaborn

Специализации: 0
ice
20
    ice ice

Специализации: 0
jiki
80
    jiki jiki

Специализации: 0
 
Статистика проекта Статистика проекта
Всего пользователей: 3050
Из них аккредитовано: 1207
Были сегодня: 17

УровеньПользователи
7481,6%
62157%
51585,2%
41665,4%
32909,5%
2411,3%
12889,4%
отсутствует184360,4%