Program ShellSort; {Сортировка Шелла, улучшение алгоритма прямого включения, разница в том, что процесс сортировки бьется на T этапов, в каждом из которых делается один проход прямого включения, но только на элементы, отстоящие друг от друга на h[i] эл-тов (i in [1..T] и h[T] = 1) Также для алгоритма прямой вставки удобно использовать "барьеры". Дабы при перемещении не сверять индекс эл-та с началом массива, удобно расширить массив на 1 эл-т (в данном случае на h[1]) и туда писать эл-т, которому собираемся искать место. Таким образом размер массива будет [-h[1]..TotalCount]. Вследствие желания создать универсальный алгоритм с использованием динамических структур (нам заранее не известно T и соответственно h[1]) будет использоваься смещенная индексация массива ( A[i] -> A[h[1]+i]). Используются улучшения Д. Кнута: h[k-1] := 3*h[k]+1; T := LOG(N,3)-1 PS. Надеюсь весь этот бред поможет вам разобраться в предложенном алгоритме.} type item = word; const MaxCount = 65530 div SizeOf(item); {Максимальное число эл-тов массива} TotalCount = 20000; type pArray = ^tArray; tArray = array [1..MaxCount] of Item; tIndex = 1..MaxCount; var T : tIndex; {Число "разбиений"} h : pArray; Fi : tIndex; {Реальный индекс первого эл-та (не барьера)} A : pArray; {--------------------------------------------------------------} Procedure Init; {Устанавливаются улучш. Кнута, иниц. массивы} var i : tIndex; begin T := round(Ln(TotalCount)/Ln(3)-1); {(С) Кнут} GetMem(h,T*SizeOf(item)); {Иниц. массив расстояний} h^[T] := 1; for i := T-1 DownTo 1 do h^[i] := 3*h^[i+1]+1; Fi := h^[1]; {Установим глоб. индекс "смещенного" смещения} GetMem(A,(TotalCount+Fi)*Sizeof(Item)); {Иницализируем осн. массив} {^^^ Для барьеров} end;{Init} {--------------------------------------------------------------} Procedure Done; {Осв. всю память} begin FreeMem(h,T*SizeOf(Item)); FreeMem(A,TotalCount*SizeOf(Item)); end;{Done} {--------------------------------------------------------------} Procedure SetArray; {Процедурка заполнения эл-тов массива случ. числами} var i : tIndex; begin Randomize; For i := 1 To TotalCount Do A^[Fi+i] := Random(65535); {^^^ Опять барьеры} end;{SetArray} {--------------------------------------------------------------} {Основная программа} Var i,j,k,m,s : tIndex; Times : pArray; x : Item; BEGIN Init; SetArray; GetMem(Times,T*SizeOF(Word)); FillChar(Times^,T*SizeOF(Word),0); For m := 1 to T do begin k := h^[m]; {Расстояние между эл-тами} s := Fi-k; {"барьер"} For i := k+1 to TotalCount do begin x := A^[Fi+i]; {Эл-т, с которым работаем} If S=Fi then S := Fi-k; inc(s); A^[s] := x; {Установим "барьер"} j := i-k; {Предыдущий через расстояние} while A^[Fi+j] > x do begin Inc(Times^[m]); A^[Fi+j+k] := A^[Fi+j]; {Двигаем массив} dec(j,k); end; A^[Fi+j+k] := x; end; end; For i := 1 to TotalCount do begin if ((i-1) mod 10) = 0 then WriteLN; Write(A^[Fi+i]:7); end; WriteLN(#10#13'Число перестановок на каждом этапе:'); for i := 1 to T do WriteLn(i,'(',H^[i],') -> ',Times^[i]); FreeMem(Times,T*SizeOF(Word)); Done; END.