Алгоритмы. Разработка алгоритма

Определение, разработка и виды алгоритма. Понятие типов и структур данных. Представление массивов, записей и множеств. Представление основных структур программирования на языке Паскаль. Основные принципы структурного и модульного программирования.

Рубрика Программирование, компьютеры и кибернетика
Вид курс лекций
Язык русский
Дата добавления 30.04.2011
Размер файла 99,5 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

writeln(s);

end.

Сравнение строк выполняется посимвольно в соответствии с их кодами до первого несовпадения. Если одна из строк закончилась до первого несовпадения, то она считается меньшей. Пустая строка меньше любой строки.

ПРИМЕР: Сравнение строк.

'abcd' > 'abcD' { 'd'>'D' }

'abcd' > 'abc' { 'd'>'' }

'abc' < 'axxc' { 'b'<'x' }

'abcd' = 'abcd'

Существует ряд стандартных функций и процедур для работы со строками.

Функция Length(s) выдает длину строки s.

Функция Concat(s1,s2,..,sn) возращает строку s1+s2+..+sn.

Функция Copy(s,p,k) возвращает фрагмент строки s, который начинается в позиции p и имеет длину k.

Функция Pos(s1,s) ищет первое вхождение подстроки s1 в строку s и возвращает номер первого символа s1 в строке s или 0 если не нашли.

Процедура Delete(s,p,k) удаляет из строки s фрагмент, который начинается в позиции p и имеет длину k.

Процедура Insert(s,s1,p) вставляет в строку s подстроку s1, начиная с заданной позиции p.

Турбо паскаль позволяет производить преобразования числовых значений в строковые и наоборот. Для этого используются процедуры Str(X:n:d,S) и Val(S,X,e). Первая получает их числа X строку S с изображением этого числа, в которой не менее n символов и из них d знаков после запятой. Параметры n и d необязательные. Вторая процедура получает из строки S число X. При успешном результате e=0.

4.5.2 Процедуры и функции

Турбо Паскаль позволяет выделять фрагменты программы во вспомогательные алгоритмы (ВА). Это позволяет писать хорошо структурированные программы. Языки программирования, в которых предусмотрены ВА, называются процедурно-ориентированными. Структурированные программы обычно проще в понимании и отладке.

В Турбо Паскале ВА оформляются в виде процедур или функций. Каждый ВА имеет собственное имя. Вызов процедуры на выполнение осуществляется отдельным оператором с помощью ее имени. Вызов функции может быть составной частью любого выражения при условии согласованности типов. Описание процедур и функций должно предшествовать их вызову и располагается перед началом основной программы. Нельзя вызывать на выполнение те ВА, которые содержатся внутри других процедур и функций. Описание процедуры имеет следующую структуру.

Procedure Имя (Список формальных параметров);

label

const Описание локальных меток,

type констант, типов и переменных

var

procedure Описание внутренних процедур

function и функций

begin

Операторы

end;

Описание функции имеет следующую структуру.

Function Имя (Список формальных параметров) : Тип результата;

label

const Описание локальных меток,

type констант, типов и переменных

var

procedure Описание внутренних процедур

function и функций

begin

Операторы, среди которых хотя бы один, который

присваивает имени функции значение результата

end.

Типом результата в функциях может быть любой из стандартных типов Турбо Паскаля кроме файловых типов. Использование конструируемых типов здесь недопустимо.

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

Исходные данные для работы ВА можно передавать через глобальные переменные, а также через параметры. Параметры при вызове ВА называются фактическими, а параметры в заголовке ВА называются формальными.

Формальные параметры ВА также относятся к его локальным переменным. Локальные данные создаются, т.е. им выделяется память, при вызове ВА, а освобождение этой памяти происходит при завершении работы ВА. В том случае, когда локальная переменная имеет тот же идентификатор, что и глобальная, алгоритм работает с локальной. При этом, значение глобальной переменной сохраняется в специальной области памяти, которая называется стек.

По способу передачи параметры в Турбо Паскале делятся на три типа:

параметры-значения,

параметры-переменные,

параметры-константы.

Параметры-значения

При вызове процедур и функций формальным параметрам-значениям выделяется новое место в памяти и присваиваются значения фактических параметров. При этом на месте фактических параметров могут стоять выражения. Совместимость типов определяется возможностями присваивания. После выполнения подпрограммы место формальных параметров освобождается. Изменение формальных параметров не сказывается на значении фактических. Заголовок процедуры с параметрами-значениями имеет вид:

Procedure MyProc1(par1,par2 : type1; par3,par4 : type2);

Параметры-переменные

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

Такой механизм передачи данных требует, чтобы фактические параметры были переменными, причем в точности того же типа, что и формальные параметры. При описании ВА перед параметрами-переменными должно присутствовать слово var. Заголовок процедуры с параметрами-переменными имеет вид:

Procedure MyProc2(var par1,par2 : type1; var par3,par4 : type2);

Параметры-константы

Работа с формальными параметрами-константами внутри ВА ведется как с обычными локальными константами. Только эти константы принимают значения выражений, которые находятся в фактических параметрах. Им не выделяется новая память как локальным переменным. Запрещается изменять их значения во время выполнения подпрограммы и контроль за этим осуществляется на уровне компилятора, как для обычных констант.

Использовать параметры-константы рекомендуется при передаче данных большого объема с гарантией сохранения их значений. Заголовок процедуры с параметрами-константами имеет вид:

Procedure MyProc3(const par1,par2 : type1; const par3,par4 : type2);

4.5.3 Открытые параметры-массивы

Открытые параметры-массивы могут быть параметрами-значениями, параметрами-переменными и параметрами-константами. Они используются для передачи массивов произвольной размерности. Заголовок процедуры с открытыми параметрами-массивами имеет вид:

Procedure OpenArray(Vector : array of MyType);

Формальный параметр при этом является массивом элементов некоторого типа MyType с нулевой базой, т.е. Array [0..N-1] of MyType; где N - количество элементов массива, которое можно определить с помощью стандартной функции High.

ПРИМЕР: Увеличение вдвое всех элементов массива.

program DoubleProgram;

const n=10; m=20;

type T1 = array[1..n] of integer;

T2 = array[-m..m] of integer;

var A : T1; B : T2; k : integer;

Procedure Double(var X : array of integer);

var i : byte;

begin

for i:=0 to High(X)-1 do X[i]:=X[i]*2;

end;

begin

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

for k:=-m to m do read(B[k]);

Double(A); {увеличение в 2 раза элементов массива A}

Double(B); {увеличение в 2 раза элементов массива B}

Double(k); {то же самое, что и присваивание k:=k*2}

writeln('k=',k); {напечатается: k=40 }

for k:=1 to n do write(A[k],' ');

writeln;

for k:=-m to m do write(B[k],' ');

end.

4.5.4 Бестиповые параметры

В Турбо Паскале существует возможность создания процедур и функций с параметрами, не имеющими типа. Бестиповые параметры могут быть параметрами-переменными и параметрами-константами, так как передаются только по адресу. Заголовок процедуры с параметрами, не имеющими типа может выглядеть таким образом:

Procedure MyProc(var par1,par2; const par3,par4);

Перед использованием формальных параметров необходимо выполнить их приведение к какому-либо типу. Использование бестиповых параметров дает большую гибкость программе, но ответственность за их корректное применение возлагается на программиста.

ПРИМЕР: Сложение первых N байт, начиная с того же места, что и X.

program without_type;

var N:word; s:string;

{$R-} (* отключение контроля за границами диапазонов *)

function Sum(var X; N:byte):word;

type A=array[1..1] of byte;

var i:byte; s:word;

begin

s:=0;

for i:=1 to n do S:=S+A(X)[i];

Sum:=s;

end;

begin

readln(s);

writeln(Sum(s,1)); {длина строки s}

writeln(Sum(s[1],1)); {код первого символа строки s}

writeln(Sum(s[1],length(s)));

{сумма кодов всех символов строки s}

read(N);

writeln(Sum(N,2));

{сумма двух байт, из которых состоит N типа word}

end.

4.5.5 Процедурные типы

В Турбо Паскале существует два процедурных типа: тип-процедура и тип-функция. Для объявления процедурного типа используется заголовок процедуры или функции без имени.

ПРИМЕР:

type Proc1 = Procedure (a,b,c : integer; x:real);

Proc2 = Procedure (var a,b);

Proc3 = Procedure;

Func1 = Function : real;

Func2 = Function (n:integer) : boolean;

Можно описывать переменные этих типов, например: var p1,p2:Proc1; f1,f2:Func2; Переменным процедурных типов можно присваивать в качестве значений имена соответствующих ВА. При этом нельзя использовать стандартные процедуры и функции. После такого присваивания имя переменной становится синонимом имени ВА. Переменные процедурного типа можно, также передавать в подпрограммы в виде параметров. Благодаря этому, имеется возможность создания более гибких вспомогательных алгоритмов.

Тема 5. Динамические стуктуры данных

5.1 Ссылочные переменные и создание на их основе списков, стеков, деревьев

Описание ссылочного типа выглядит следующим образом:

Type Ptr = ^t,

где t -- стандартный или заранее описанный тип данных, называемый базовым типом. Сами адреса будут храниться в ссылочных переменных, которые описываются обычным образом, например, Var P : Ptr. Такие переменные называются ссылками или указателями.

Список -- это набор записей, каждая из которых имеет поле данных и указатель (ссылку) на следующую запись в списке. Та, в свою очередь, тоже содержит поле данных и ссылку на продолжение списка. Последний элемент списка содержит значение Nil, т. е. уже ни на что не ссылается. Начало списка формирует переменная типа “указатель”, содержащая адрес первого элемента списка. Поле данных еще называют информационной частью списка.

Пример описания элемента списка, информационная часть которого - переменная типа Integer:

Type lst_ptr = ^lst_type;

lst_type=record

data : integer;

next : lst_ptr;

End;

Список обычно задается указателем на свой первый элемент. Пусть это указатель р.

Добавление элемента в начало списка можно осуществить при помощи следующей последовательности операторов:

New(q);{Выделение памяти для элемента списка}

Readln(q^.data);{Задаем информационную часть списка}

q^.next:=p; {Связали элемент с остальными элементами списка}

P:=q; {Перенесли указатель на начало, т.е. на добавленный элемент}

Основными операциями над списками являются:

переход от элемента к следующему элементу;

включение нового элемента в список;

исключение элемента из списка.

Стек -- линейный список, в котором добавления и исключения элемента производятся с одного конца, называемого вершиной стека.

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

Пример:

Фрагмент программы, в котором формируется список целых чисел, полученных с помощью датчика случайных чисел:

p := nil;

For i:= 1 To 10 Do

Begin

New(q);

q^.data := random(100);

q^.next := p;

p := q;

End;

Процедура обхода элементов списка и вывода содержимого каждого элемента на экран:

Procedure pass_l(L : lst_ptr);

{Входной параметр: L типа lst_ptr - указатель на первый элемент списка.}

Var p : lst_ptr;

Begin

p:=L; {Встать на начало списка.}

While p<> nil Do {Пока не конец списка.}

Begin

Writeln(p^.data); {Вывести содержимое списка.}

p:=p^.next; {Перейти к следующему элементу списка.}

End;

End;

Процедура поиска в списке элемента, содержащего искомые данные:

Procedure seach(L : lst_ptr; key : integer; Var p : lst_ptr);

{Входные параметры:

L - типа lst_ptr - указатель на начало списка, в котором производится поиск;

key - значение данных, которое должен содержать искомый элемент (ключ поиска).

Выходной параметр:

p - типа lst_ptr - указатель на элемент списка, содержащего искомые данные, в случае отсутствия такого элемента равен nil.}

Begin

p := L;

While (p<>nil) and (p^.data<>key) Do p:=p^.next;

End;

Процедура, добавляющая в список элемент p после элемента q:

Procedure add_after(p,q : lst_ptr);

{Входные параметры:

p типа lst_ptr - указатель на вставляемый элемент.

q типа lst_ptr - указатель на элемент списка, после которого вставляется элемент p.}

Begin

p^.next:=q^.next;

q^.next:=p;

End;

Процедура удаления из списка элемента p:

Procedure del(p : lst_ptr; Var L : lst_ptr);

{Параметры: р - ссылка на удаляемый элемент; L - ссылка на первый элемент списка.}

Var q : lst_ptr;

{q - рабочий указатель, который будет ссылаться на элемент, предшествующий р}

Begin

If p<> L Then {если р - не первый элемент списка}

Begin

q:=L; {поиск элемента, предшествующего р}

While q^.next <> p Do q := q^.next;

q^.next := p^.next;

End

else {Обработка случая, когда удаляется первый элемент списка}

L := p^.next;

End;

Добавить элемент в стек:

New(q); Readln(q^.x); q^.next := p; p := q;

Считать значение элемента из стека и исключить его из стека:

q := p; p := q^.next; y := q^.x; dispose(q);

Считать элемент, не удаляя его из стека:

y := p^.x;

Тема 6. Алгоритмы поиска

6.1 Линейный поиск

6.2 Поиск с барьером

6.3 Двоичный (бинарный) поиск

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

6.1 Линейный поиск

Линейный поиск осуществляется циклом (while или repeat - until) с двойным условием. Первое условие контролирует индекс на принадлежность массиву, например, (i<=N). Второе условие - это условие поиска. В нашем случае в цикле while это условие продолжения поиска: (A[i]<>X), а в цикле repeat - until это условие завершения поиска: (A[i]=X). В теле цикла обычно пишется только один оператор: изменение индекса в массиве.

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

ПРИМЕР: Линейный поиск

program Poisk1;

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

N, X, i:integer;

begin

read(N); {N<=100}

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

read(X);

i:=1; {i:=0;}

while (i<=N) and (A[i]<>X) do i:=i+1;

{repeat i:=i+1; until (i>N) or (A[i]=X);}

if i<=N then write('первое вхождение числа ',X,'

в массив A на ',i,' месте')

else write('не нашли');

end.

При поиске последнего вхождения после ввода должны идти операторы:

i:=N; {i:=N+1;}

while (i>=1) and (A[i]<>X) do i:=i-1;

{repeat i:=i-1; until (i<1) or (A[i]=X);}

if i>=1 then write('последнее вхождение числа ',X,' в массив A на ',i,' месте')

else write('не нашли');

6.2 Поиск с барьером

Идея поиска с барьером состоит в том, чтобы не проверять каждый раз в цикле условие, связанное с границами массива. Это можно обеспечить, установив в массив так называемый барьер: любой элемент, который удовлетворяет условию поиска. Тем самым будет ограничено изменение индекса.

Выход из цикла, в котором теперь остается только условие поиска, может произойти либо на найденном элементе, либо на барьере. Таким образом, после выхода из цикла проверяется, не барьер ли мы нашли? Вычислительная сложность поиска с барьером меньше, чем у линейного поиска, но также является величиной того же порядка, что и N - количество элементов массива.

Существует два способа установки барьера: дополнительным элементом или вместо крайнего элемента массива.

ПРИМЕР: Поиск с барьером

program Poisk2a;

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

N,X,i:integer;

begin

read(N); {N<=100}

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

read(X);

A[N+1]:=X; {установка барьера дополнительным элементом}

i:=1; {i:=0;}

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

{repeat i:=i+1; until A[i]=X;}

if i<=N then write('первое вхождение числа ',X,' в массив A на ',i,' месте')

else write('не нашли');

end.

program Poisk2b;

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

N,X,i,y:integer;

begin

read(N); {N<=100}

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

read(X);

y:=A[N]; {сохранение последнего элемента}

A[N]:=X; {установка барьера на последнее место массива}

i:=1; {i:=0;}

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

{repeat i:=i+1; until A[i]=X;}

if (i<N) or (y=X) then

write('первое вхождение числа ',X,' в массив A на ',i,' месте')

else write('не нашли');

A[N]:=y; {восстановление последнего элемента массива}

end.

6.3 Двоичный (бинарный) поиск

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

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

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

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

ПРИМЕР: Поиск в упорядоченном по возрастанию массиве первого вхождения числа X.

program Poisk3a;

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

N,X,left,right:integer;

begin

read(N); {N<=100}

write('введите упорядоченный по возрастанию массив');

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

read(X);

left:=1; right:=N;

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

while left<right do

begin

c:=(left + right) div 2;

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

if X>A[c] then

{если массив упорядочен по убыванию, то if X<A[c]}

left:=c+1

{выбираем правую половину без середины, меняя left}

else right:=c;

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

end;

if X=A[left] then {здесь left = right, но не всегда = c}

write('первое вхождение числа ',X,' в массив A на ',left,' месте')

else write('не нашли');

end.

ПРИМЕР: Поиск в массиве, упорядоченном по возрастанию сумм цифр элементов массива, последнего числа с суммой цифр равной X.

program Poisk3b;

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

N,X,left,right:integer;

{функция считает сумму цифр числа a, здесь a - локальная переменная}

function Sum(a:integer):integer;

var s:integer;

begin

s:=0; a:=abs(a);

while a>0 do

begin

s:=s + a mod 10;

a:=a div 10;

end;

Sum:=s;

end;

begin

read(N); {N<=100}

write('введите массив, упорядоченный по возрастанию сумм цифр');

{например, для N=4 : 122, -432, 88, 593}

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

read(X);

left:=1; right:=N;

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

while left<right do

begin

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

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

if X>=Sum(A[c]) then left:=c

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

else right:=c-1;

{выбираем левую половину без середины, меняя right}

end;

if X=Sum(A[left]) then {здесь left = right, но не всегда = c}

write('последнее число с суммой цифр=',X,' равно',A[left], ' находится в массиве A на ',left,' месте')

else write('не нашли');

end.

Тема 7. Рекурсия

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

ПРИМЕР: Вычислить N-е число Фиббоначчи. (Смотри тему Циклы)

program Fib;

var n:byte;

function F(k:byte):word;

begin

if k<2 then F:=1 else F:=F(k-1)+F(k-2); {рекурсивный вызов}

end;

begin

write('введите номер числа Фиббоначчи ');

readln(N);

writeln(N,'-е число Фиббоначчи =',F(N));

readln

end.

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

ПРИМЕР: Неявная рекурсия.

Procedure B(x:byte); forward;

Procedure A(y:byte);

begin

- - -

B(y);

- - -

end;

Procedure B;

begin

- - -

A(x);

- - -

end;

РЕКОМЕНДАЦИИ: Необходимо по возможности избегать применения рекурсии, так как большая глубина рекурсивных вызовов часто приводит к переполнению стека. В некоторых случаях проблему можно устранить, установив новый размер стека от 1024 до 65520 байт с помощью директивы

{$M размер стека, нижняя граница, верхняя граница памяти}

Типизированные константы

Кроме обычных констант в Турбо Паскале можно использовать типизированные константы, которые фактически являются переменными с начальными значениями. Они описываются в разделе Const в форме:

<имя типизированной константы> : <тип> = <значение>;

ПРИМЕР:

const x : integer = 10; y : real = 3.14;

A : array[1..5] of integer = (1,2,-3,24,0);

B : array[1..2,-1..1] of byte = ((1,2,3),(4,5,6));

R : record m : string[10]; d,y : integer; end =

(m : 'January'; d : 20; y : 1999);

S : string[4] = 'abcd';

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

ПРИМЕР: Использование типизированных констант

program typed_const;

var N:integer;

procedure Test;

const k:integer=1;

begin

if k<N then

begin

writeln(k,'-й вызов процедуры');

k:=k+1;

Test;

end

else writeln('последний вызов процедуры');

end;

begin

read(N);

if N>0 then Test;

end.

Тема 8. Алгоритмы сортировки

8.1 Сортировка выбором

8.2 Сортировка обменом (методом "пузырька")

Простейшая задача сортировки заключается в упорядочении элементов массива по возрастанию или убыванию. Другой задачей является упорядочение элементов массива в соответствии с некоторым критерием. Обычно в качестве такого критерия выступают значения определенной функции, аргументами которой выступают элементы массива. Эту функцию принято называть упорядочивающей функцией.

Существуют различные методы сортировки. Будем рассматривать каждый из методов на примере задачи сортировки по возрастанию массива из N целых чисел.

8.1 Сортировка выбором

Идея метода заключается в том, что находится максимальный элемент массива и меняется местами с последним элементом (с номером N). Затем, максимум ищется среди элементов с первого до предпоследнего и ставится на N-1 место, и так далее. Необходимо найти N-1 максимум. Можно искать не максимум, а минимум и ставить его на первое, второе и так далее место. Также применяют модификацию этого метода с одновременным поиском максимума и минимума. В этом случае количество шагов внешнего цикла N div 2.

Вычислительная сложность сортировки выбором - величина порядка N*N, что обычно записывают как O(N*N). Это объясняется тем, что количество сравнений при поиске первого максимума равно N-1. Затем N-2, N-3, и так далее до 1, итого: N*(N-1)/2.

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

program Sort_Vybor1;

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

N,i,m,k,x : integer;

begin

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

read(N);

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

for k:=n downto 2 do { k - количество элементов для поиска max }

begin

m:=1; { m - место max }

for i:=2 to k do if A[i]>A[m] then m:=i;

{меняем местами элементы с номером m и номером k}

x:=A[m]; A[m]:=A[k]; A[k]:=x;

end;

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

end.

ПРИМЕР: Та же задача с одновременным выбором max и min.

program Sort_Vybor2;

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

N,i,m,k,x,p : integer;

begin

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

read(N);

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

for k:=1 to n div 2 do { k - номер пары max и min }

begin

m:=k; { m - место max }

p:=k; { p - место min }

{max и min ищутся среди элементов с k до n-k+1}

for i:=k+1 to n-k+1 do

if A[i]>A[m] then m:=i

else if A[i]<A[p] then p:=i;

{меняем местами элементы с номером p и номером k}

x:=A[p]; A[p]:=A[k]; A[k]:=x;

if m=k then m:=p;

{если max стоял на месте k, то сейчас он на месте p}

{меняем местами элементы с номером m и номером n-k+1}

x:=A[m]; A[m]:=A[n-k+1]; A[n-k+1]:=x;

end;

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

end.

8.2 Сортировка обменом (методом "пузырька")

Идея метода заключается в том, что последовательно сравниваются пары соседних элементов массива. Если они располагаются не в том порядке, то совершаем перестановку, меняя местами пару соседних элементов. После одного такого прохода на последнем месте номер N окажется максимальный элемент ("всплыл" первый "пузырек"). Следующий проход должен рассматривать элементы до предпоследнего и так далее. Всего требуется N-1 проход. Вычислительная сложность сортировки обменом O(N*N).

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

program Sort_Obmen1;

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

N,i,k,x : integer;

begin

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

read(N);

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

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

for i:=1 to k do

if A[i]>A[i+1] then

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

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

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

end.

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

ПРИМЕР: Сортировка обменом с проверкой факта перестановки.

program Sort_Obmen2;

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

N,i,k,x : integer; p:boolean;

begin

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

read(N);

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

k:=n-1; {количество пар при первом проходе}

p:=true; {логическая переменная p истинна, если были

перестановки, т.е. нужно продолжать сортировку}

while p do

begin

p:=false;

{Начало нового прохода. Пока перестановок не было.}

for i:=1 to k do

if A[i]>A[i+1] then

begin

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

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

p:=true; {и запоминаем факт перестановки}

end;

k:=k-1;

{уменьшаем количество пар для следующего прохода}

end;

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

end.

Следующая модификация алгоритма сортировки обменом получается при запоминании места последней перестановки. Если при очередном проходе последней парой элементов, которые поменялись местами, были A[i] и A[i+1], то элементы массива с i+1 до последнего уже стоят на своих местах. Использование этой информации позволяет нам сделать количество пар для следующего прохода равным i-1.

ПРИМЕР: Сортировка обменом с запоминанием места последней перестановки.

program Sort_Obmen3;

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

N,i,k,x,m : integer;

begin

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

read(N);

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

k:=n-1; {количество пар при первом проходе}

while k>0 do

begin

m:=0;

{пока перестановок на этом проходе нет, место равно 0}

for i:=1 to k do

if A[i]>A[i+1] then

begin

x:=A[i]; A[i]:=A[i+1]; A[i+1]:=x; {меняем элементы местами}

m:=i; {и запоминаем место перестановки}

end;

k:=m-1; {количество пар зависит от места последней перестановки}

end;

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

end.

Список литературы и источников по темам (к лекциям)

1. Немнюгин С.А. Turbo Pascal. : СПб.: Издательство "Питер", 2000.

2. Немнюгин С.А. Turbo Pascal: практикум : СПб.: Издательство "Питер", 2001.

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

4. Культин Н.Б. Турбо Паскаль в задачах и примерах. - Спб.: БХВ-Петербург, 2002.-

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

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

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

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

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

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

11. Маќамбаев М.Б., Ќабланбекова Б.А. Турбо Паскаль программалау ортасы. Алматы, КаНУ, 2000 ж.

12. Г.Ж.Есенбекова Практикум по информатике.Алматы 2002

Размещено на Allbest.ru


Подобные документы

  • История формирования традиционной технологии программирования. Задачи и предмет структурного программирования, как одного из крупнейших достижений в технологии программирования. Подпрограмма, типы управляющих структур. Понятие модульного программирования.

    презентация [1,8 M], добавлен 05.11.2016

  • Изучение символьных и строковых типов данных, алгоритма задачи на языке программирования Паскаль. Описания получения и установки отдельного символа строки, изменения регистра символов. Анализ создания и просмотра файла, поиска и сортировки информации.

    курсовая работа [440,7 K], добавлен 13.06.2011

  • Методика и технологический прием структурного программирования; построение алгоритма программы логической задачи в виде блок-схемы из структур "следование, ветвление, цикл"; кодирование текста программы, языки структурного программирования Паскаль и Си.

    реферат [623,5 K], добавлен 25.03.2012

  • Структура – это объединение одного либо более объектов (переменных, массивов, указателей, других структур). Понятие структурной переменной. Создание массивов структур. Использование вложенных структур в виде элементов массивов person, date, pibm.

    лабораторная работа [17,6 K], добавлен 15.07.2010

  • Приобретение теоретических и практических навыков программирования на языке Паскаль. Математическая формулировка задачи и выбор метода обработки информации. Разработка алгоритма и его описание. Описание программы. Форма представления исходных данных.

    курсовая работа [224,3 K], добавлен 11.02.2016

  • Анализ заданной сложной функции и разработка структурной схемы алгоритма по её вычислению. Программирование отдельных блоков и структур алгоритма решаемой задачи на языке Паскаль. Полная программа в соответствии с алгоритмом. Результаты расчётов на ПК.

    курсовая работа [59,2 K], добавлен 09.04.2012

  • Язык программирования Турбо Паскаль. Запись алгоритма на языке программирования и отладка программы. Правила записи арифметических выражений. Стандартное расширение имени файла, созданного системным редактором. Составной оператор и вложенные условия.

    курсовая работа [75,0 K], добавлен 21.03.2013

  • Анализ функции и разработка алгоритма по ее вычислению. Программирование отдельных блоков и структур алгоритма. Структура Паскаль-программы. Раздел описаний, подпрограммы, тело программы. Полная Паскаль-программа в соответствии с разработанным алгоритмом.

    курсовая работа [241,8 K], добавлен 30.01.2016

  • Выбор метода проектирования транслятора с языка Паскаль на язык Си, разработка и кодирование алгоритма программы. Использование допустимых операторов в исходном тексте, определение типов переменных и синтаксиса логических и арифметических выражений.

    курсовая работа [1,0 M], добавлен 03.07.2011

  • Понятие алгоритма и сортировки. Способы и алгоритмы сортировки массивов. Быстрая сортировка Хоара. Описание алгоритма "быстрой сортировки". Реализация на языке программирования. Анализ наихудшего разбиения. Вероятностные алгоритмы быстрой сортировки.

    курсовая работа [291,5 K], добавлен 22.03.2012

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.