Алгоритм построения дерева иерархии выглядит следующим образом.
Вход:
hList – линейный массив значений иерархии предварительно отсортированный по полю Code. Count – число элементов массива hList.
Выход:
hTree – двумерный массив, представляющий дерево иерархии. Внутри hTree хранятся ссылки на элементы hList. LevelCount – количество уровней иерархии и соответственно ширина массива hTree. Cnt – число узлов на каждом из уровней дерева hTree.
Часть 1. Заполнение поля Level для элементов иерархии, получение количества уровней. | ||
1 | LevelCount ← 0 | // количество уровней равно 0 |
2 | for i ← 0 to Count - 1 do | // обходятся все элементы |
begin | // списка значений иерархии | |
3 | idx ← i | // текущий элемент равен i |
4 | if hList[idx].Level < 0 then | // если узел не обработан, то |
begin | // обрабатываем | |
5 | if hList [idx].Parent < hList [idx].Code | // строим диапазон поиска |
then begin | // предка. Если Parent < Code, то | |
6 | is ← 0 | // диапазон поиска от 0 |
7 | ie ← Index – 1 | // до ТекущийЭлемент – 1 |
end else | ||
8 | if hList [idx].Parent > hList [idx].Code | // в обратном случае |
then begin | // диапазон поиска от | |
9 | is ← idx + 1 | // текущего элемента + 1 |
10 | ie ← Count – 1 | // до последнего элемента |
end else | // иначе элемент ссылается на | |
11 | return Error | // себя, и следовательно ошибка |
12 | Parent ← Find(hList [idx].Parent, is, ie) | // ищем предка в диапазоне |
13 | if (Parent = -1) or (hList [Parent].Level >= 0) | // если предок является корнем или уже обработан, то |
then begin | // выполняем след. действия: | |
14 | if Parent = - 1 then | // если предок корень, то |
15 | hList [idx].Level ← 0 else | // устанавливаем уровень в 0 |
16 | hList [idx].Level ← hList [Parent].Level + 1 | // иначе уровень равен уровню предка + 1 |
17 | LevelCount ← MAX(hList [idx].Level + 1, LevelCount) | // обновляем максимальное число уровней |
18 | hList [idx].Parent ← Parent | // присваиваем значение предка |
end else | // иначе если узел еще не | |
begin | // обработан, то | |
19 | Povtor2: hList [Parent].FirstChildIndex ← idx | // ставим метку и сохраняем значение текущего индекса в неиспользуемом пока поле |
20 | idx ← Parent | // текущий индекс выставляем по значению предка |
21 | if hList[idx].Parent < hList[idx].Code | // как в пунктах 5-11 |
then begin | // строим диапазон поиска | |
22 | is ← 0 | // предка |
23 | ie ← idx – 1 | |
24 | end else | |
25 | if hList[idx].Parent > hList[idx].Code | |
then begin | ||
26 | is ← idx + 1 | |
27 | ie ← Count – 1 | |
end else | ||
28 | return Error | |
29 | Parent ← Find(hList[idx].Parent, is, ie) | // ищем предка в построенном диапазоне |
Povtor: | // ставим метку | |
30 | if (Parent = -1) or (hList[Parent].Level >= 0) | // если этот предок обработан |
then begin | // то повторяем пункты 14-18 | |
31 | if Parent = -1 then | |
32 | hList[idx].Level ← 0 else | |
33 | hList[idx].Level ← hList[Parent].Level + 1 | |
34 | LevelCount ← MAX(hList [idx].Level + 1, LevelCount) | |
35 | hList [idx].Parent ← Parent | |
36 | if hList[idx].FirstChildIndex = -1 | // проверяем поле – есть нет |
37 | then continue | // сохранного значения, то прекращаем обработку текущего элемента |
38 | Parent ← idx | // иначе сохраняем в Parent текущее значение |
39 | idx ← hList[Parent].FirstChildIndex | // восстанавливаем текущее значение из сохраненного |
40 | hList[Parent].FirstChildIndex ← -1 | // сбрасываем сохраненное значение |
41 | goto Povtor | // и возвращаемся к пункту 30 |
end else | // если и этот предок не был обработан и не являлся корнем | |
42 | goto Povtor2 | // то возвращаемся в пункт 19 |
end | ||
end else | // если исходный узел уже был | |
43 | LevelCount ← MAX(hList [idx].Level + 1, LevelCount) | // обработан, то обновляем максимальное число уровней |
end | ||
Часть 2. Заполнение структуры дерева | ||
44 | for i ← 0 to count - 1 do | // обходятся все элементы |
begin | // списка значений иерархии | |
43 | cnt[hList[i].Level] ← cnt[hList[i].Level] + 1 | // увеличивается количество элементов на уровне |
44 | hTree[hList[i].Level][cnt[hList[i].Level] – 1] ← hList[i] | // узлу дерева присваивается ссылка на запись в списке |
end | ||
45 | for i ← 0 to LevelCount - 1 do | // восстановление Parent по |
begin | // значению из базы | |
46 | if i = 0 then | // для всех элементов нулевого |
begin | // уровня значения Parent | |
47 | for j ← 0 to cnt[i] - 1 do | // приравниваются к -1 |
48 | hTree[i][j].Parent ← -1 | |
end else | // для других уровней | |
49 | for j ← 0 to cnt[i] - 1 do | // значение получается из |
50 | hTree[i][j].Parent ← hList[hTree[i][j].Parent].LevelIndex | // заранее сохраненной в поле LevelIndex информации |
51 | SortLevel(i) | // внутри уровня i все элементы сортируются в алфавитном порядке |
52 | for j ← 0 to cnt[i] - 1 do | // внутри уровня обходятся все |
begin | // элементы | |
53 | hTree[i][j].LevelIndex ← j | // устанавливается значение индекса на уровне |
54 | if (i <> 0) and (if HierTree[i - 1] [HierTree[i][j].Parent].FirstChildIndex = -1) then | // для не нулевого уровня и еще не обработанных элементов |
55 | hTree[i - 1][hTree[i][j].Parent]. FirstChildIndex ← j | // устанавливается ссылка на первого потомка |
end | ||
end |
Сложность алгоритма
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 |


