Здравствуйте.
В этот раз в статья много картинок, без них она не имеет смысла, так что
их желательно загрузить.
Пирамидальная сортировка.
Дерево -- коллекция узлов, каждый из которых (кроме корневого)
имеет родительский узел и какое-то количество дочерних узлов.
Узлы, которые не имеют дочерних узлов называют листьями.
Дерево называют бинарным, если все узлы содержат не более двух
дочерних узлов.
Узлы бинарного дерева описываются так:
type
PTreeNode=^TTreeNode
TTreeNode = record
ptParent, ptLChild, ptRChild :PTreeNode;
Data :integer;
end;
Бинарное
дерево называется пирамидой, если:
1) Все листья расположены на двух последних уровнях.
2) Предпоследний уровень заполнен полностью, а в последнем все элементы
максимально сдвинуты влево..
3) Дочерние узлы меньше родительских или равны им.
Разберём подробней 3 пункт. Но сначала надо определиться с тем, как
хранить пирамиду. Использовать указатели в нашем случае не выгодно.
Зная особенности пирамиды, правильнее хранить её в массиве.
На основе этого массива построим бинарное дерево, обладающее двумя первыми
признаками пирамиды.
Чтобы начать преобразовывать это дерево в пирамиду надо рассмотреть алгоритм
просачивания.
Допустим, дерево представляет из себя две пирамиды соединённые корневым
узлом(см. рисунок 2). Будем применять алгоритм просачивания для [0]
элемента. Сравним его с наибольшим дочерним элементом ([0] c [1]). Так
как [0] элемент меньше то обменяем их (см. рис. 3). На следующем этапе
все эти операции проведём для [1] элемента, и т. д. до тех пор пока
1 не встанет(просочиться) на своё место (рис.
4).
procedure HeapDown(_Ind, _MaxInd : integer);
var
ChildInd, StartValue:integer;
begin
StartValue:=a[_Ind];
ChildInd:=(_Ind*2)+1;
while ChildInd <= _MaxInd dobeginif (ChildInd + 1 <= _MaxInd) and (a[ChildInd] < a[ChildInd+1]) then
inc(ChildInd);
if StartValue >= a[ChildInd] then break;
a[_Ind]:=a[ChildInd];
_Ind:=ChildInd;
ChildInd:=(_Ind * 2) + 1
end;
a[_Ind]:=StartValue;
end;
Вернёмся к задаче. Для построения пирамиды необходимо, начиная с родительского
узла самого правого дочернего узла просочить все элементы расположенные
левее и не ниже. В нашем случае (рис.1) это элементы с 0-го по 6-ой.
procedure GenerateHeap(_MaxInd:integer);
var
i:integer;
beginfor i:=(_MaxInd-1) div 2 downto 0 do
HeapDown(i,_MaxInd);
end;
Самая интересная особенность пирамиды в том, что максимальный элемент
всегда наверху (докажите). Но как её использовать. Надо поменят местами
корневой и последний элементы и уменьшить кол-во элементов на 1. В нашем
примере мы должны в 0-ую позицию поместить 81. Свойство пирамидальности
скорее всего будет нарушено и для восстановления оного надо будет применить
алгоритм просачивания для нового корневого элемента. И так до тех пор
пока кол-во элементов в массиве больше 1.
while L>=1 dobegin
t:=a[L];a[L]:=a[0];a[0]:=t;
Dec(L);
HeapDown(0, L);
end;