Смекни!
smekni.com

Языки и технология программирования (стр. 8 из 8)

Этот алгоритм, по сути, является модификацией сортировки обменом. Отличие состоит только в том, что если в сортировке обменом проходы осуществлялись только в одном направлении, то здесь направление каждый раз меняется. В шейкерной сортировке также можно проверять факт перестановки или запоминать место последней перестановки. В базовом алгоритме количество двойных проходов равно N div 2. Вычислительная сложность шейкерной сортировки O(N*N).

ПРИМЕР: Шейкерная сортировка по возрастанию массива A из N целых чисел.

program Shaker;

var A:array[1..100] of integer;

N,i,k,x,j,d : integer;

begin

write('количество элементов массива ');

read(N);

for i:=1 to n do read(A[i]);

d:=1; i:=0;

for k:=n-1 downto 1 do { k - количество сравниваемых пар }

begin

i:=i+d;

for j:=1 to k do

begin

if (A[i]-A[i+d])*d>0 then

{меняем местами соседние элементы}

begin x:=A[i]; A[i]:=A[i+d]; A[i+d]:=x; end;

i:=i+d;

end;

d:=-d;

{меняем направление движения на противоположное}

end;

for i:=1 to n do write(A[i],' '); {упорядоченный массив}

end.

СОРТИРОВКА ВКЛЮЧЕНИЕМ

Идея данного метода состоит в том, что каждый раз, имея уже упорядоченный массив из K элементов, мы добавляем еще один элемент, включая его в массив таким образом, чтобы упорядоченность не нарушилась. Сортировка может производиться одновременно со вводом массива.

В начале сортировки упорядоченная часть массива содержит только один элемент, который вводится отдельно или, если массив уже имеется, считается единственным, стоящим на нужном месте. Различные методы поиска места для включаемого элемента приводят к различным модификациям сортировки включением.

При использовании линейного поиска вычислительная сложность сортировки включением составляет O(N*N), а при использовании двоичного поиска - O(N*LogN) (имеется в виду логарифм по основанию 2).

ПРИМЕР: Сортировка по возрастанию массива A из N целых чисел включением с линейным поиском.

program Sort_Include1;

var A:array[1..100] of integer;

N,i,k,x : integer;

begin

write('количество элементов массива ');

read(N);

read(A[1]); {for i:=1 to n do read(A[i]);}

{k - количество элементов в упорядоченной части массива}

for k:=1 to n-1 do

begin

read(x); {x:=A[k+1];}

i:=k;

while (i>0)and(A[i]>x) do

begin

A[i+1]:=A[i];

i:=i-1;

end;

A[i+1]:=x;

end;

for i:=1 to n do write(A[i],' '); {упорядоченный массив}

end.

ПРИМЕР: Сортировка по возрастанию массива A из N целых чисел включением с двоичным поиском.

program Sort_Include2;

var A:array[1..100] of integer;

N,i,k,x,c,left,right : integer;

begin

write('количество элементов массива '); read(N);

read(A[1]); {for i:=1 to n do read(A[i]);}

{k - количество элементов в упорядоченной части массива}

for k:=1 to n-1 do

begin

read(x); {x:=A[k+1];}

left:=1; right:=k;

{левая и правая граница фрагмента для поиска}

while left<right do

{двоичный поиск последнего вхождения}

begin

c:=(left+right+1) div 2;

{середина с округлением в большую сторону}

if x>=A[c] then left:=c

{берем правую половину с серединой}

else right:=c-1; {берем левую половину без середины}

end;

if x>=A[left] then left:=left+1;

{сдвигаем на 1 вправо часть массива, освобождая место

для включения x}

for i:=k downto left do A[i+1]:=A[i];

A[left]:=x;

end;

for i:=1 to n do write(A[i],' '); {упорядоченный массив}

end.

СОРТИРОВКА ХОАРА

Эту сортировку также называют быстрой сортировкой. Метод был разработан в 1962 году профессором Оксфордского университета К. Хоаром. Это прекрасный пример использования рекурсии. Рассмотрим принцип работы алгоритма при упорядочении массива A из N элементов по возрастанию.

Значение какого-нибудь элемента, обычно центрального, записывается в переменную X. Просматриваются элементы массива. При движении слева-направо ищем элемент больше или равный X. А при движении справа-налево ищем элемент меньше или равный X. Найденные элементы меняются местами и продолжается встречный поиск.

После этого массив окажется разделенным на две части. В первой находятся элементы меньше либо равные X, а справа - больше либо равные X. Можно заменить исходную задачу о сортировке массива A на две подзадачи о сортировке полученных частей массива.

Вычислительная сложность одного вызова данного рекурсивного алгоритма пропорциональна количеству элементов сортируемого фрагмента массива. В лучшем случае деление на части производится пополам, поэтому вычислительная сложность всего алгоритма быстрой сортировки составляет величину порядка N*LogN (логарифм по основанию 2). Вычислительная сложность в среднем того же порядка.

ПРИМЕР: Быстрая сортировка по возрастанию массива A из N целых чисел.

program Quick_Sort;

var A:array[1..100] of integer;

N,i : integer;

{В процедуру передаются левая и правая границы сортируемого фрагмента}

procedure QSort(L,R:integer);

var X,y,i,j:integer;

begin

X:=A[(L+R) div 2];

i:=L; j:=R;

while i<=j do

begin

while A[i]<X do i:=i+1;

while A[j]>X do j:=j-1;

if i<=j then

begin

y:=A[i]; A[i]:=A[j]; A[j]:=y;

i:=i+1; j:=j-1;

end;

end;

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

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

end;

begin

write('количество элементов массива ');

read(N);

for i:=1 to n do read(A[i]);

QSort(1,n); {упорядочить элементы с первого до n-го}

for i:=1 to n do write(A[i],' '); {упорядоченный массив}

end.

СОРТИРОВКА С ИСПОЛЬЗОВАНИЕМ ВЕКТОРА ИНДЕКСОВ

В отличии от всех ранее изложенных методов сортировки, этот не является самостоятельным алгоритмом, а представляет собой идею, которую можно применять к любому из них. Идея заключается в том, что вводится дополнительный массив B, который принято называть вектором индексов. Числа в нем говорят о том, в каком порядке нужно смотреть на элементы из A, например:

Массив A : 4 7 3 5 Массив B : 3 1 4 2 { A[3] A[1] A[4] A[2] }

В начале программы в вектор индексов B записываются последовательно натуральные числа от 1 до N. При работе любой сортировки вместо элемента A[i] обращаются к элементу A[B[i]]. Это сделано для того, чтобы менять местами не элементы массива A, а их индексы, т.е. элементы массива B.

МОДУЛЬ CRT (основные возможности)

Модуль Crt относится к стандартным модулям Турбо Паскаля и находится в файле turbo.tpl (Turbo Pascal Library). Для подключения модуля достаточно написать uses Crt. Модуль Crt содержит средства управления экраном в текстовом режиме и клавиатурой.

На экране используются два активных цвета: цвет текста и цвет фона. Их можно установить с помощью процедур TextColor и TextBackground, которые имеют по одному параметру: целому числу, задающему номер цвета. Для цвета текста используются числа от 0 до 15, а для цвета фона - от 0 до 7. Обе эти процедуры оказывают влияние только на последующий вывод.

Координаты на экране задаются следующим образом. Левый верхний угол имеет координаты (1,1), а правый нижний (80,25). Можно вводить относительные координаты, объявляя окно с помощью процедуры Window(x1,y1,x2,y2), где x1,y1 - абсолютные координаты левого верхнего, а x2,y2 - правого нижнего угла окна. После этого все процедуры и функции кроме Window используют относительные координаты. Вернуться к работе со всем экраном можно, написав Window(1,1,80,25). С помощью процедуры GotoXY(x,y) можно установить курсор в заданную позицию окна, а с помощью пары функций WhereX и WhereY без параметров можно узнать текущие координаты курсора. Процедура ClrScr не имеет параметров и закрашивает текущее окно цветом фона.

Модуль Crt позволяет осуществлять контроль клавиатуры. Известно, что информация о нажатых клавишах поступает сначала в буфер клавиатуры и только затем считывается компьютером. Также известно, что клавиши и комбинации клавиш делятся на обычные, и управляющие. В результате нажатия обычной клавиши в буфер клавиатуры поступает ее код, который может быть от 1 до 255, а при нажатии управляющей клавиши в буфер клавиатуры поступает два кода, первый из которых 0. Функция KeyPressed не имеет параметров и возвращает истиный результат если буфер не пуст. При этом содержимое буфера не изменяется. Функция ReadKey также не имеет параметров и забирает из буфера клавиатуры очередное число, возвращая в программу символ (тип char), код которого соответствует этому числу. В случае, когда буфер пуст, функция ReadKey ожидает нажатия на клавиатуре.


ЛИТЕРАТУРА

1. Абрамов А.Г., Трифонов Н.П., Трифонова Г.Н. Введение в язык Паскаль. М., Наука, 1988.

2. Абрамов С.А., Гнездилова Г.Г., Капустина Е.Н., Селюн М.И. Задачи по программированию. М., Наука, 1988.

3. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. М., Мир, 1979.

4. Вирт Н. Алгоритмы и структуры данных. М., Мир, 1989.

5. Епанешников А., Епанешников В. Программирование в среде Turbo Pascal 7.0. М., Диалог-Мифи, 1993.

6. Зуев Е.А. Система программирования Turbo Pascal. М., Радио и связь, 1992.

7. Зуев Е.А. Программирование на языке Турбо-Паскаль 6.0,7.0. М. Радио и связь. Веста. 1993.

8. Йодан Э. Структурное программирование и конструирование программ. М.: Мир, 1979.

9. Кенин А.М., Печенкина Н.С. Работа на IBM PC. М., АО "Книга и бизнес", 1992.

10. Кнут Д. Искусство программирования на ЭВМ. М.: МИР, т.1, 1976; т.2, 1977; т.3, 1978.

11. Липский В. Комбинаторика для программистов. М., Мир, 1988.

12. Майерс Г. Искусство тестирование программ. М.: Финансы и статистика, 1982. Гласс Р., Нуазо Р. Сопровождение программного обеспечения, М.: Мир, 1983.

13. Пильщиков В.Н. Сборник упражнений по языку Паскаль. М., Наука, 1989.

14. Поляков Д.Б., Круглов И.Ю. Программирование в среде Турбо Паскаль (версия 5.5). Изд-во МАИ, 1992.

15. Рейнгольд Э., Нивергельт Ю., Део Н. Комбинаторные алгоритмы. М., Мир, 1980.

16. Фаронов В.В. Турбо Паскаль 7.0. Начальный курс. М., Нолидж, 1997.

17. Фаронов В.В. Турбо Паскаль 7.0. Практика программирования. М., Нолидж, 1997.

18. Шень А. Программирование: Теоремы и задачи. М., МЦНМО, 1995.