Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2771
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

4, Структурные типы данных

3 . 5 ^ ^ 0.5]-2.1 Г9П 3.5 I 0.5 { Щ 1-2.1 I 9.8

ПП

б

Рис. 4.11. Этапы выполнения программы:

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

цу, если обнаружен еще один элемент, который необходимо оставить в мас­ сиве. При этом оставляемый элемент переписывается на место, указанное данной переменной (рис. 4.11). После завершения цикла просмотра массива переменная к содержит размер массива. Элементы, содержащиеся в остальной части массива, на экран не выводятся.

Если в массиве не содержится элементов, удовлетворяющих заданному условию, то при просмотре массива мы перепишем элементы сами в себя, а значение к будет равно п.

Алгоритмы с отдельной и встроенной реализацией сдвига элементов по­ казаны на рис. 4.12.

Реализуем второй более простой вариант.

Program ex;

Var a:array[l.,10] of integer; Д /, k n:integer;

Begin

WriteLnf'Введите количество элементов « <= 10');

ReadLn(n);

 

WriteLn(*Введите \n,'

элементов массива *);

for i:^l

to n do Read(a[i]);

ReadLn;

{вводим массив}

WriteLnCBeedume В:

*);

ReadLn(B); {вводим В}

WriteLnC Исходный массив ');

for i:-l

to n do Write(a[i]:5);

FTrteZw; {выводим исходный масср^в}

k:-0;

{пока не найдено ни одного элемента массива}

91

Часть I. Основы алгоритмизации и процедурное программирование

Вывод

У

 

/"Массив

/

у^

N.

/

/

/

пуст"

/

( К о н е ц !

А(п),п

{Конец )

Рис. 4.12. Два алгоритма удаления из массива элементов меньше В:

а - с отдельным циклом сдвига; б-со встроенным циклом сдвига

for /:=i to п do begin

ifA[i]>^B then begin

A[k]:^A[i];

end

end;

ifk^O then WriteLnCBce элементы вычеркнуты. Массив пуст. ^) else

92

4. Структурные типы данных

begin

WriteLnC Результирующий массив из % к, * элеменпюв:^); for i:-l to к do Write(a[i]:5);

WriteLn;

end;

End,

В некоторых случаях при переформировании массива его размер не ме­ няется. Примерами подобной обработки служат перестановки различного характера (см., например, сортировку массивов в параграфе 4.3).

Одновременная обработка нескольких массивов или подмассивов. К

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

Пример 4.7. Разработать программу формирования из массива целого типа А(п), где п < 40, нового массива В, содержащего только положительные элементы массива А.

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

Program ex;

Var a,b:array[L,40] of integer; /, k n:integer;

Begin

WriteLn(*Введите количество элементов массива <=40*); ReadLnfn);

WriteLn(*Введите \п, * элементов массива А *); for i:=] to п do Read(a[i]);

ReadLn;

WriteLn(*Исходный массив: '); fori:=ltondo Write(a[i]:3); WriteLn;

93

Часть 1. Основы алгоритмизации и процедурное программирова

Аг;=0;{начальное значение индекса формируемого массива} for i:-l to п do

ifa[i]>0 then {если элемент > 0} begin

k:=k+l; {изменение индекса формируемого массива} b[k]:-a[i]; {перепись найденного элемента}

end; ifk=-0 then

WriteLnCB массиве A нет пололсительньрс элементов. *)

else begin

WriteLnC массив результат В'); for i:^l to к do Write(b[i]:3); WriteLn;

end;

End,

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

Существует несколько методов поиска. Самый простой заключается в последовательном просмотре элементов массива. Если массив не очень боль­ шой, затраты времени линейного поиска не столь заметны. Но при солидных объемах информации время поиска становится критичным. Поэтому сущест­ вуют методы, позволяющие уменьшить время поиска, например двоичный поиск, который применяется только, если элементы массива сортированы по возрастанию или убыванию (см. пример 4.19).

Чаще всего при программировании поисковых задач используют циклыдо или циклы-пока, в которых условие выхода формируется из двух условий (см. параграф 3.6): первое условие - пока искомый элемент не найден, а вто­ рое - пока есть элементы массива. После выхода из цикла осуществляют проверку, по какому из условий произошел выход.

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

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

94

4.Структурные типы данных

Не с т р у к т у р н ы й а л г о р и т м , в котором просмотр осуществля­ ется с помощью счетного цикла, а выход обеспечивается операторами goto или break, рассматривать не будем.

Реализуем с т р у к т у р н ы й а л г о р и т м , в котором для просмот­ ра элементов используется цикл-пока со сложным условием: пока элементы не отрицательны и индекс элемента не вышел за границы массива. Элемент, на котором прервался цикл, если его индекс не превышает размера массива, и есть искомый.

Program ex;Var а:array[L, 100] of integer; iJ,n: integer;

Begin

WriteLn(*Beedume количество элементов n <= J00'); ReadLn(n);

WriteLn(*Введите \n, * элементов массива *); for i:=I to n do Read(a[i]);

ReadLn;

WriteLnC Исходный массив ');

for i:=I to n do Write(a[i]:5); WriteLn;

i:-l; {начальное значение индекса массива}

while (afij>=0) and (i<n) do i:=i+l; {пока элемент не отрицателен

и индекс меньше п - переходим к следующему элементу}

ifi<-n then

WriteLnCnepebiu отрицательный элемент ^,afij:5, * имеет индекс %'4)

else WriteLnCTuKux элементов в массиве нет, У;

End

Задания для самопроверки

Задание 1. Дан одномерный массив вещественных чисел А(п), где п < 50. Раз­ работайте профамму, формирующую новый массив В из элементов массива А, ко­ торые превышают среднее арифметическое элементов массива А, стоящих на местах с четными индексами. Выведите среднее арифметическое значение элементов мас­ сива А, исходный и сформированный массивы.

Задание 2. Дан одномерный целочисленный массив С(п), где п < 40, содержа­ щий как положительные, так и отрицательные элементы. Разработайте профамму, которая определяет номер первого отрицательного элемента, по абсолютной величи­ не превышающего максимальный элемент этого массива. Выведите массив С, а так­ же номер найденного элемента, или соответствующее сообщение, если такого эле­ мента нет.

Задание 3. Разработайте программу, которая формирует массив В(п), п < 30, со­ держащий элементы целого типа в диапазоне от -20 до 130, используя датчик слу-

95

Часть I. Основы алгоритмизации и процедурное программирование

чайных чисел. В сформированном массиве определите количество и среднее ариф­ метическое положительных и отрицательных элементов массива. Переменной логи­ ческого типа Flag присвоить True, если среднее арифметическое отрицательных чи­ сел по абсолютной величине больше среднего арифметического положительных чи­ сел, и False, если нет. Выведите массив В, а также все найденные в программе вели­ чины.

Задание 4. Дан массив Т(п), п < 20, вещественного типа. Разработайте програм­ му, которая вычисляет произведение максимального по абсолютной величине эле­ мента заданного массива на его же первый отрицательный элемент, если таковой имеется. Выведите исходный массив и произведение, или сообщение о невозможно­ сти вычисления произведения.

Задание 5. Дан массив D(n), п < 10, вещественного типа. Разработайте програм­ му, которая вычисляет сумму трех первых положительных элементов заданного мас­ сива. Если таких элементов нет, программа должна выдавать соответствующее сооб­ щение. Выведите на печать исходный массив и искомую сумму.

4.3.Практикум. Сортировка массивов. Оценка вычислительной сложности алгоритма

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

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

В качестве оценки производительности методов обычно используют функциональную зависимость времени работы программы от размерности исходного массива t(n). При анализе алгоритмов в первую очередь интерес представляет характер зависимости при достаточно больших значениях раз­ мерности задачи (п -»оо).

Б математике характер зависимости часто определяют ее порядком. Порядком некоторой функции t(n) при достаточно больших п называют другую

функцию g(n), такую, что

 

 

 

 

lim

t(n)

= const Ф 0.

 

n->oo g(n)

 

Это обозначается как

t(n) = 0[g(n)].

96

4. Структурные типы данных

Например, для полинома f(rt) = 20"* - Зп^ + 5п - 6, порядком является по­ лином п"*, или f(n) = О(п^), так как

lim 2п4 - ЗпЗ + 5п - 6 =2.

п->оо j|4

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

сложность O(const) означает, что время решения задачи с использованием данного метода не зависит от размерности задачи, 0(п) - время работы про­ порционально размерности задачи, 0(v?-) - время работы пропорционально квадрату размерности задачи и т. д.

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

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

На практике интересны методы сортировки, которые позволяют эконом­ но использовать оперативную память, поэтому целесообразно рассмотреть только методы, не требующие использования дополнительных массивов. Та­ кие методы в практике программирования называют прямыми. Самыми про­ стыми из прямых методов являются:

метод выбора;

метод вставки;

метод обменов (метод пузырька). Рассмотрим эти методы на конкретном примере.

Пример 4.9, Разработать программу сортировки элементов массива

А(п), где п < 20, используя метод выбора, метод вставки и метод обменов. Оценить эффективность применения указанных методов.

Метод выбора. Сортировка посредством выбора представляет собой один из самых простых методов сортировки. Он предполагает такую после­ довательность действий.

Сначала находим минимальный элемент массива. Найденный элемент меняем местами с первым элементом. Затем повторяем процесс с п-1 элемен-

97

Часть 1, Основы алгоритмизации и процедурное программирование

 

 

п

 

 

amm

imin

 

7.8 -6.3 5.8 ^ 1.2

8.4

4.5

Ьй проход

 

 

 

К,^

м 1

 

 

amin

imin

 

ШЩ!^ 5.8

1.2

8.4

4.5

2-й проход

IF]

[Т]

 

 

n-2

 

 

 

 

amin

imin

 

 

 

 

 

3-й проход

5.8

7.8

8.4

4.5

[ID Ш

 

 

 

 

 

n-3

 

amin

imin

 

mwm^f^

 

4-й проход

 

on ш

5-й проход

wtm^xi^f^

 

amin

imin

7.8

[тг]

H

 

 

 

 

 

 

^^тштж^шШЩ

Рис. 4.13. Сортировка выбором

тами, начиная со второго, потом с п-2 элементами, начиная с третьего и т.д. до тех пор, пока не останется один, самый большой элемент массива (рис. 4.13).

Алгоритм сортировки выбором приведен на рис. 4.14. Ниже приведен текст программы, реализующий данный алгоритм.

Program sortl;

Var a:array[L.20] of real; y, /, w, imin:mteger; mm:real;

Begin

WritelnCBeedume количество чисел n<=20: *); Readln(n);

Writeln('Введите массив: *); for i:=^l to n do Read(a[i]); Readln;

forj:-l to n-l do {цикл поиска минимальных элементов массива} begin

mn:^4i[j]; {начальное значение для поиска минимума} imin:^j; {начальное значение индекса минимального элемента} for i:-jH to п do {цикл поиска минимума и его индекса}

ifa[i]<min then {если элемент меньше уже найденного минимального}

98

Рис. 4.14. Алгоритм сортировки выбором

4. Структурные типы данных

begin

min:—a[i]; {запоминаем элемент}

imin:-i {запоминаем его индекс}

end;

{меняем местами найденный минимум и первый элемент текущего массива}

a[imin]:=a[j];

a[iJ:=ntin;

end;

for i:=] to n do Write(a[i]:6:2); Writeln;

End.

Оценим временную сложность данного метода, используя в качестве основной опе­ рации операцию сравнения.

Для поиска минимального элемента в каждом проходе потребуется выполнить: п-1, п-2, ..., 1 операций сравнения, т.е. всего п(п-1)/2 операций сравнения. Следователь­ но, вычислительная сложность данного ме­ тода 0(п2). Причем время сортировки не за­ висит от исходного порядка элементов.

Метод вставки. Сортировку вставками можно описать следующим образом. В ис­ ходном состоянии считают, что сортируемая

последовательность состоит из двух последовательностей: уже сортирован­ ной (она на первом шаге состоит из единственного - первого элемента) и по­ следовательности элементов, которые еще необходимо сортировать. На каж­ дом шаге из сортируемой последовательности извлекается элемент и встав­ ляется в первую последовательность так, чтобы она оставалась сортирован­ ной. Поиск места вставки осуществляют с конца, сравнивая вставляемый элемент а; с очередным элементом сортированной последовательности а:. Если элемент aj больше а:, его вставляют вместо aj^.], иначе сдвигают а: вправо и уменьшают] на единицу. Поиск места вставки завершают, если эле­ мент вставлен или достигнут левый конец массива. В последнем случае эле­ мент aj вставляют на первое место (рис. 4.15).

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

99

Часть 1. Основы алгоритмизации и процедурное программирование

1 7.8 -6.3 5.8 1.2 8.4 4.5 1

1-й

^о\/

1.2

7.8

ГГЛ

 

проход

-6.3

5.8

4.5

MJ Ш

2-й

 

ГГл

. ГГл

MJ Ш

-6.3

1.2

5.8

4.5

7.8

проход

 

 

 

n-l

 

 

 

 

З-й

-6.3

1.2

4.5

5.8

%% Ж1 Ш

проход

 

 

п-2

 

 

 

 

4-й

-6.3

1.2

4.5

$Л\1Л\ЬА\

Ш

проход

 

 

п-3

 

 

 

 

 

 

[-6.3

1.2

4.5

5.8

7.8

8.4

1

Рис. 4.15. Сортировка вставками

(

Начало

J

/

Ввод

7

/

"> ^">

/

 

i:=2,n,l

 

 

31

 

 

B:=A[i]

 

 

А[0]:=В

 

jH-l

A[i]>B нет

Ж.

AD+1]:=AD]

j:=j.l

Л

А0+1]:=В

Вывод У

А(п) /

/

Г Конец j

Рис. 4.16. Схема алгоритма сорти­ ровки вставками

из цикла поиска места вставки в любом случае происходил выход по перво­ му условию. Для этого достаточно поместить вставляемый элемент перед первым элементом массива, как элемент с индексом 0. Этот элемент и станет естественным барьером для ограничения выхода за левую границу массива.

Алгоритм сортировки вставками приведен на рис. 4.16. Ниже приведен текст программы, реализующей данный алгоритм.

Program sort2;

Var a:arrayfO.,20J of real; В.real; ij\n:mteger;

Begin

WriteLn(*Введите количество чисел n<=20,');

100