9 Окт »

Пирамидальная сортировка

Автор: Основной язык сайта | В категории: Изучаем информатику
1 кол2 пара3 трояк4 хорошо5 отлично (Еще не оценили)
Загрузка...

Описанное здесь сортировка в среднем медленнее, чем быстрое, хотя и имеет сложность в наиболее плохом случае B(n\ogn) . Тем не менее этот алгоритм применяется для сортировки файлов и решение некоторых других задач. Пирамидальная сортировка (или сортировка с помощью груды) использует бинарное дерево (пирамиду). Рассмотрим цс понятие. Расположим элементы массива с индексами 1..к строками, удваивая количество элементов в строках: в первой строке — первый элемент (с индексом 1), во второму — с индексами 2 и 3, в третьему — с индексами 4-7, дальше— 8-15 и т.п.. Последняя строка может остаться неполным, Например, при п = 10 будет образована пирамида индексов, как на рисунке.

Рассмотрим пирамиду как бинарное дерево с корнем наверху и листвой внизу. Дерево образовано узлами, которые відловідають индексам, и связями между ними — дугами. Корнем дерева является узел 1. Узлы 2 и С назовем сыновьями узла І (их отца), узлы 4 и 5 — сыновьями 2 и т.п.. Узлы, которые не имеют сынов, называются листками (на рисунке это узлы 6-10. Итак, если узел и имеет сынов, то ими есть узлы с индексами 11 и 2/ + 1, а его отцом является узел с индексом / div 2.

Дальше будем рассматривать узлы дерева, которые содержат значение элементов массива с соответствующими индексами, Для сортировки важным есть упорядочения значений в массиве, за который при каждому возможному и исполняется неровность А\\ div 2] >/4[j], т.е. «сын не больше отца». Это свойство не касается лишь корня дерева, поскольку он не имеет отца. Дерево с этим свойством называют правильным, или правильной грудой. Рассмотрим пример правильного дерева, которое отвечает последовательности значений

Сортировка с помощью груды использует то, что корень правильной груды содержит ее максимальное значение. Сначала в массиве образуем правильную груду, дальше поменяем местами значения первого элемента массива (корня дерева) и последнего. Наибольшее значение займет «свое» последнее место в массиве, и дальше о нем можно забыть. Среди сдачи элементов массива восстановим основное свойство груды и обменяем местами значения первого элемента и теперь уже предпоследнего, и так будем действовать дальше, пока дерево не сократится до одного элемента. procedure   heapSort(var   A:alnt;   n:word);

var   j:word;    {индекс   последнего} begin

build(A,n);    {начальное   построение   хупи} for   j:=n   downto   2   do   begin swap(A[l],A[j]);

rebuild(A,1,j-1)    {восстановление  правильности} end end;

Сначала уточним процедуру rebuild восстановление правильности груды. Если значение в корневом узле изменилось, основное свойство в нем может не выполняться, поэтому по потребности больший из сынов обменивается с отцом, после чего основное свойство проверяется и восстанавливается для сына. Действия из восстановление правильности груды в части массива А]/], …, A[d] нетрудно уточнить рекурсивной процедурой.

  • procedure   rebuild(var  A:alnt;   f,d:word); var   maxSon:word;    {индекс   максимального   сына} begin
  • maxSon:=f;
  • if    (2*f<=d)and(A[f]<A[2*f])
  • then  maxSon   :=   2*f;
  • if    (2*f+K=d) and(A[maxSon]<A[2*f+1])
  • then maxSon:=2*f+1; if   maxSonOf   then   begin swap(A[f] r[maxSon]) ; rebuild<A,maxSon,d); end; end;
  • Приведенная процедура является примером так называемой «хвостовой ре-курсії», когда после рекурсивного вызова нет никаких действий. В подобных ситуациях рекурсию можно заменить циклом, условие завершения которого отвечает условию «дна рекурсн». Очевидно также, что перестройку дерева можно закончить, если значение максимального сына и отца местами не обменивались. В этой ситуации, чтобы прекратить выполнение цикла, присвоим индекса «отца» f значение за пределами части массива, который перестраивается. Итак, приведем нерекурсивный вариант процедуры rebuild, procedure   rebuild(var   A.alnt;    f,d:word); var  maxSon:word;    {индекс   максимального   сына} begin
  • while (2*f<=d)do begin
  • maxSon:=f;
  • if   <M?]<A[2*ff]) then maxSon:=2*f;
  • if    (2*f+K=d)andCA[raaxSon]<   A[2*f+1]) then maxSon:=2*f+l; if   maxSonOf   then  begin swap(A[f],A[maxSon]);
  • f :=maxSon  -{дальше  перестройка пирамиды сына} end
  • else   f:=d+l; end;
  • {2*f   >  d   или   A[f]    >= A[maxSon]} end;

В конце концов уточним начальное построение груды за процедурой build. Заметим, что в массиве с п элементами максимальным ‘индексом узла-отца есть п div 2. Итак, последовательно образуем правильные груды в піддеревах, корнями которых являются узлы п div 2, п div 2 — и,…, 1. Это разрешит утверждать, что построенный массив представляет собой правильную груду.

  • procedure build(var A:alnt; n:word); var и:word;
  • begin
  • for i:=n div 2 downto 1 do
  • rebuild(A,i,n); {перестройка чаотини массива}
  • end;

Оценим сложность алгоритма. Очевидно, что она прямо пропорциональная общему количеству вызовов rebuild. При выполнении build процедура rebuild вызывается п div 2 раза, а при выполнении цикла for процедуры treeSort — еще л — 2 раза, т.е. общее количество вызовов процедуры rebuild из других процедур есть ®(п).

Оценим сложность выполнения одного вызова процедуры rebuild. Заметим, что в цикле значения сменной f не менее чем удваивается, а цикл не будет продлеваться, если это значение станет больше d, которое не больше г. Итак, таких удвоений не может быть больше чем |_log2 п\ . Количество действий в теле цикла является константой, поэтому общая сложность имеет оценку 0{n\ogn). Высотой узла дерева называют количество ребер в наиболее длинном пути из этой вершины вниз к листкам; высоту корня называют высотой дерева. Дерево, которое образовано как пирамида с п узлов, имеет высоту log2 п .

Сочинение! Обязательно сохрани - » Пирамидальная сортировка . Потом не будешь искать!


Всезнайкин блог © 2009-2015