Var I,j:Word;

w:Tzp; x:Tk;

begin

i:=L;j=R;

x:=a[(L+R) div 2].k;

Repeat

While a[i].k<x do i:=i+1;

While a[j].k>x do j:=j-1;

if i<=j then begin

w:=a[i];a[i]:=a[j];a[j]:=w;i=i+1;j=j-1;

end;

until i>j;

if L<j then sort(L,j);

if i<R then sort(i,R);

end; //sort

begin

sort(1,n);

end;

В ниже приведенном не рекурсивном варианте процедуры сортировки для организации списка введен массив stak[s], 0sM:

Не рекурсивный вариант сортировки Хоара:

Листинг 3.10

Procedure QuickSort(Var a:mas;n:Word);//nMr

const M=12;

Var I,j,l,r:Word; X:Tk; w:Tzp;

s:0..M;

stak:array[1..M] of record L,R:word end;

begin

s:=1; stak[1].L:=1; stak[1].R:=n;

Repeat //выбор из Steka последнего запроса

L:=stak[s].L; R:stak[s].R; s:=s-1;

Repeat //разделение a[L]...a[R]

i:=L; j:=R; x:=a[L+Rаndom(R-L+1)].k;

Repeat

While a[i].k<x do i:=i+1;

While a[j].k>x do j:=j-1;

if i<=j then begin

w:=a[i];a[i]=a[j];a[j]:=w;i=i+1;j=j-1 end;

until i>j;

if j-L<R-i then //какая половина длинее?

begin

if i<r then //запись в Stak запроса из правой части

begin s:=s+1; stak[s].L:=i; stak[s].R:=R; end

R:=j;

end //теперь L и R ограничивают левую часть

else

begin

if L<j then//запись в stak запроса из левой части

begin s:=s+1;stak[s].L:=L;stak[s].R:=j end

L:=i

end;

until L>=R;//конец разделения очередной части

until s=0;//stak пуст

end;//QuickSort.

Для повышения устойчивости Хоар рекомендует выбирать «средний» элемент случайным образом:

x:=a[L+Random(R-L+1)].k;

Метод быстрой сортировки «не любит» массивов, имеющих много одинаковых элементов, а также больших отсортированных участков.

Сравнение методов сортировок показывает, что при n>100 наихудшим является метод пузырька, метод QuickSort в 2-3 раза эффективнее, чем HeapSort, и в 3-7 раз чем метод Шелла. Метод сортировки слиянием самый быстрый по времени, однако требует значительных затрат памяти. Поэтому он обычно используется для внешних сортировок.

Тема 4. Связанные списки с использованием рекурсивных данных

4.1. Список, стек, очередь

В практике программирования довольно часто встречается задача обработки набора однотипных данных Inf1, Inf2, ...... Infn, количество которых n меняется в зависимости от ситуации. Их надо разместить в оперативной памяти и по мере надобности с ними работать: добавлять новые данные в список, освобождаться от старых данных, выдавать информацию о количестве данных, находить нужную информацию. Показательным примером является задача обслуживания очереди заказов на покупку товара. Данные Infi могут содержать информацию о заказчике: ФИО, адрес, финансовые возможности и др. По мере появления новых заказчиков их дописывают в конец очереди (Infn+1, Infn+2, ....), по мере поступления товара, и обслуживания заказчиков из начала очереди данные Inf1, Inf2,... об этих заказчиках стираются. При решении подобных задач программисты вводят понятие списка.

Список (list) – это последовательность однотипных элементов (данных), с которыми надо работать в оперативной памяти: добавлять новые элементы, удалять использованные, сортировать, находить нужные. В процессе работы список может возрастать и уменьшаться. Наибольшее распространение получили две формы работы со списком – очередь и стек.

Очередь (turn) – это список с двумя точками входа. С одной стороны последовательности данные добавляются в список (в конец очереди), с другой стороны списка данные удаляются из него (из начала очереди). Таким образом реализуется принцип – «первый пришел – первый вышел». Наглядный пример – трубка, заполняемая шариками, имеющими диаметр, равный диаметру трубки. С одной стороны трубки шарики добавляются в нее, с другой вынимаются.

Стек (stek) – это список с одной точкой входа. Данные добавляются в список и удаляются из него только с одной стороны последовательности (вершины стека). Таким образом реализуется принцип – «последний пришел – первым вышел». Наглядный пример – трубка, запаянная с одного конца и заполняемая шариками, имеющими диаметр, равный диаметру трубки. С одной стороны трубки шарики добавляются в нее и вынимаются.