Информатика_всем
.pdf985.3 Элементы, удовлетворяющие некоторому условию (поиск)
5.3Элементы, удовлетворяющие некоторому условию (поиск)
Зачастую в обработке массивов требуется обработать не все элементы, а лишь те, которые удовлетворяют некоторому условию. Для этого в тело цикла вставляют развилку с условием, накладываемым на элементы. Блок-схема таковой обработки представлена на Рисунок 5.5. Условие может быть каким угодно, например, положительность, равенство чему-либо, четность и т.д.
Рисунок 5.5 Обработка элементов массива, удовлетворяющих некоторому условию
ПРИМЕР
Рассмотрим задачу подсчета среднего арифметического четных элементов массива. Решением будет являться следующий алгоритм, записанный в виде блок-схемы (Рисунок 5.6) и в виде программы:
program massiv;
var A:array[1..100] of integer; i,k,N:byte;
S:integer;
SrA:real; begin
writeLn(‘Введите количество элементов в массиве’); readLn(N);
for i:=1 to N do begin
write(‘A[’,i,’]=’);
readLn(A[i]);
end;
S:=0;
k:=0;
for i:=1 to N do
if (A[i] mod 2) = 0 then begin
S:=S+A[i];
100 5.3 Элементы, удовлетворяющие некоторому условию (поиск)
Здесь после подсчета суммы и количества делается проверка на существование четных элементов. Четные элементы существуют в том случае, если условие четности выполнилось хотя бы один раз. Это приведет к инкрементации переменной k, служащей счетчиком четных элементов, на единицу. Инкрементация – процесс увеличения переменной. Декрементация, соответственно – процесс уменьшения значения переменной
(от англ. increase – возрастание, decrease – уменьшение).
Использование счетчика k есть частный случай рекуррентного алгоритма подсчета суммы. Только в этом случае при каждой удачной итерации k увеличивается строго на единицу (счетчик «перещелкивается»).
В случае отсутствия в массиве четных элементов, переменная k останется равной нулю, что приведет к попытке деления на ноль. Для предотвращения этого мы в алгоритм после цикла вставили развилку, которая выводит значение среднего арифметического или сообщение о невозможности его подсчета.
ПРИМЕР
Аналогичным образом можно провести подсчет среднего геометрического модулей четных элементов. Только в этом случае будет использоваться рекуррентный алгоритм накопления произведения. При этом не забываем умножать на модуль значения найденного четного элемента. Найдем k – количество четных элементов массива, найдем P – произведение
этих элементов. Далее, если k не равно нулю, вычислим SrG =
будем извлекать используя формулу возведения в степень с помощью функций доступных языку Pascal:
x y = exp( y ln(x))
Не приводя блок-схемы, запишем фрагмент программы подсчитывающей среднее геометрическое модуля четных элементов одномерного массива:
…
P:=1;
k:=0;
for i:=1 to N do
if (A[i] mod 2) = 0 then begin
P:=P*abs(A[i]);
k:=k+1;
end;
if k<>0 then begin
SrG := exp((1/k)*ln(P));
writeLn(‘Среднее геометрическое: ’, SrG:8:2); end
else
writeLn(‘В массиве нет четных элементов’);
…
5. Одномерные массивы |
101 |
Иногда по условию задачи требуется сформировать из заданного массива новый. Решим такую задачу:
ПРИМЕР
Из положительных элементов массива A сформировать массив B, а из отрицательных и кратных трем сформировать массив C.
Рисунок 5.7 Формирование из одного массива пары новых |
Алгоритм достаточно прост:
Nb:=0;
Nc:=0;
for i:=1 to Na do if A[i]>0 then
begin Nb:=Nb+1; B[Nb]:=A[i];
end else
if (A[i]<0) and (A[i] mod 3 = 0 ) then begin
Nc:=Nc+1; C[Nc] := A[i];
end;
102 5.3 Элементы, удовлетворяющие некоторому условию (поиск)
Блок-схема изображена на (Рисунок 5.7). Здесь внутри цикла записана полная развилка. На положительной ветви ведется формирование массива B, а на отрицательной располагается еще одна развилка со сложным условием, в случае выполнения которого будет формироваться массив C. В качестве переменных индексов массивов C и B используются переменные Nb и Nc, которые после окончания цикла будут равны, соответственно, числу элементов массива B и C.
Одними из самых важных алгоритмов поиска в массивах являются алгоритмы отыскания экстремальных элементов в них. Простейшими примерами экстремальных элементов являются максимальный и минимальный по значению.
Алгоритм поиска максимума и его места расположения (индекса) достаточно прост. Упрощенно его можно представить следующим образом: Пусть у нас есть кучка камней и нам нужно найти наибольший среди них. Для этого мы берем в левую руку первый камень и считаем что он самый большой. Далее берем в правую руку следующий камень и сравниваем его с тем что находится в левой. Если камень в правой руке больше того, что в левой, то мы освобождаем левую руку и перекладываем в нее содержимое правой. Если ситуация обратная (в правой руке камень меньше чем в левой), то все оставляем без изменения. Правую руку освобождаем и вытаскиваем ею следующий камень для анализа. И так продолжает до тех пор, пока не переберем все камни в куче.
На языке алгоритма это будет выглядеть так (Рисунок 5.8):
Рисунок 5.8 Поиск максимума и его индекса |
5. Одномерные массивы |
103 |
…
max := A[1]; Imax := 1;
for i:=1 to N do if A[i]>max then
begin
max:= A[i]; Imax:= i;
end;
…
Алгоритм поиска минимума точно такой же, только знак «>» меняется на «<» и переменным даются имена, отражающие суть того, что ведется поиск минимального элемента (min и Imin).
Не всегда поиск элементов происходит по одному условию. Иногда этих условий несколько. Если их совокупность можно объединить операциями алгебры логики и просто заключить в один предикатный узел, то все достаточно просто. Однако, иногда не удается просто так включить сложное условие, поскольку может нарушаться свойство массовости алгоритма. Для этого поступают в каждом конкретном случае по-своему. Для примера рассмотрим достаточно типичную задачу такого характера:
ПРИМЕР
Найти наименьший элемент среди нечетных элементов массива.
Для этой задачи составим тестовый пример:
вход: A = |
−8 |
−1 |
2 |
3 |
6 |
−7 |
4 |
−10 |
1 |
−5 |
выход: min = –7; Imin = 6
Если попытаться применить алгоритм, описанный ранее с добавлением в условие требования нечетности элемента, то результатом будет min= –8, что явно неверно. Это связано с тем, что хотя мы и накладываем условие нечетности на элементы, оно не применится к точке входа (к первому элементу массива). Для корректной работы алгоритма требуется правильно задать первый элемент, принимаемый за минимум. Для этого его сначала надо найти. В качестве алгоритма решения задачи можно предложить такой (Рисунок 5.9):
Imin:=1;
while (not odd(A[Imin])) and (Imin<=N) do Imin:=Imin+1;
if Imin<=N then begin
min := A[Imin];
for i:= Imin+1 to N do
if A[i]<min) and (odd(A[i]) then begin min:=A[i]; Imin:=i;
end;
end else
writeLn(‘в массиве нет нечетных элементов’);
104 5.3 Элементы, удовлетворяющие некоторому условию (поиск)
Imin := 1 |
(Not odd(A[Imin])) |
and (Imin ≤ N) |
Imin := Imin+1 |
Imin ≤ N |
min := A[Imin]
‘В массиве нет нечетных элементов’
i := Imin+1 , N |
(A[i] < min) and |
odd(A[i]) |
min := A[i] |
Imin := i |
Рисунок 5.9 Поиск минимального среди нечетных в два последовательных цикла
Здесь при помощи цикла с предусловием сначала ищется первый нечетный элемент, после чего первый цикл прерывается и начинается второй с того места, где закончился предыдущий. А место это, как раз находится там, где встретился нечетный элемент массива. Второй цикл – обыкновенный алгоритм поиска минимума с дополнительным условием нечетности. Данный алгоритм предполагает наличие хоть одного нечетного элемента в составе массива. Для решения этой задачи можно предложить немного иной алгоритм, суть которого сводится к использованию всего одного цикла и переменной логического типа. Приведем решение задачи альтернативным способом целиком (Рисунок 5.10).