Эффективность алгоритма по времени
Прежде, чем рассмотреть задачу поиска данного элемента, отметим важную отличительную особенность алгоритмов обработки массивов: их сложность определяется характерными параметрами - размерами исходных массивов. Поэтому качество алгоритма, реализованного в виде программы и не зависящее от внешних обстоятельств, можно оценить функцией параметра задачи. При этом основное свойство функции оценки сложности - скорость ее роста.
Для алгоритма поиска эта функция растет линейно.
Этот факт отражен формулой T(n) = O(n).
Сложность простых алгоритмов сортировки оценивается квадратичной функцией.
Поэтому T(n) = O(n2). (Точное определение записи О(n) дано в математическом анализе.)
Абстрагирование от деталей реализации программы дает возможность оценивать алгоритмы решения задач и их реализацию в виде программы. Мерой эффективности алгоритма является оценка его сложности.
Задача поиска данного элемента в массиве. Очевидный алгоритм ее решения, как и в предыдущей задаче - последовательный просмотр массива и сравнение каждого элемента массива с данным. Отличие состоит в том, что когда элемент найден, просмотр можно прекратить. Это означает, что выполнение цикла прерывается. В языке имеется средство прерывания - оператор перехода.
Пример 2. Поиск данного элемента в массиве.
Program Search_in_Array;
Label 1;
Const n = 100;
Var A: Array[1..n] of Real;
b: Real; Flag: Boolean; i: Integer;
Begin
{Блок чтения массива A и элемента b}
Flag := true;
For i := 1 to n do
If A[i] = b then begin
Flag := false; goto 1
end; {прерывание цикла}
1:If Flag
then Writeln(‘Элемент ‘,b,’в массиве отсутствует’)
else Writeln(‘элемент ‘,b,’стоит на’,i,’-том месте’);
End.
Рассмотрим красивое решение этой задачи без применения оператора Goto. Это решение использует цикл While вместо использования цикла For c досрочным выходом при помощи Goto:
Program WhileSearch;
Const n = 100;
Var A : Array[1..n] of Real;
b : Real; i : Integer;
Begin
{Блок чтения массива A и элемента b}
i := 1;
While (i <= n) and (A[i] <> b) do i := Succ(i);
If i = n + 1
then Writeln(‘Элемент‘,b,’в массиве отсутствует’)
else Writeln(‘элемент ‘,b,’ расположен на ’,i,’ -том месте’);
End.
Недостатком такой реализации является во-первых, использование сложного условия в цикле, во-вторых - возможно некорректное вычисление подвыражения A[i] <> b при i = n +1. Несмотря на то, что условие заведомо ложно (i <= n = False), выражение A[n+1] <> b не определено! Дополним массив A еще одним элементом: A[n+1] = b, и все недостатки легко устраняются!
Program LinearSearch;
Const n = 101; { Размер массива увеличен на 1 }
Var A : Array[1..n] of Real;
b : Real; i : Integer;
Begin
{ Блок чтения массива A и элемента b }
i := 1;
A[n] := b; { Дополнили массив “барьерным” элементом }
While A[i] <> b do i := Succ(i);
If i = n
then Writeln(‘Элемент ‘,b,’в массиве отсутствует’)
else Writeln(‘элемент ‘,b,’расположен на’,i,’-том месте’);
End.
Рис 2. Поиск места элемента в массиве методом линейного просмотра с барьером.
b – элемент, место которого необходимо найти. Перед 1-ым шагом просмотра в массиве устанавливают барьер: A[n] := b. На i-том шаге просмотра A[i] сравнивается с b. Алгоритм заканчивает работу при A[i] = b. Если при этом окажется, что i = n, искомый элемент в массиве отсутствует. В противном случае i - его место. Наличие барьера гарантирует корректное завершение цикла.
