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

3345

.pdf
Скачиваний:
2
Добавлен:
15.11.2022
Размер:
4.34 Mб
Скачать

зуется частная производная его результата по j-му параметру

R

Чa .

j

Ее также вычисляют методом проб, после того, как модель (алгоритм) создана. Однако на практике при построении сложных моделей очень важно знать ее чувствительность до начала создания. Тут также действуют по шагам, предъявляя требования к чувствительности (точности) каждого блока модели. Требования задают в виде необходимости разрешения (получения раздельно) двух самых близких значений получаемых результатов. Например, если требуется получить раздельно результаты RА и RВ, отстоящие друг от друга на min-ом расстоянии, то модель будет чувствительной, если эти результаты будут отстоять на расстоянии 6 , где - величина среднеквадратической ошибки моделирования.

Однако, правильность и чувствительность алгоритма еще ничего не говорят о его эффективности. Рассмотрим, что это такое.

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

Какие основные переменные? Каких они типов?

Сколько нужно массивов и какой размерности? Имеет ли смысл пользоваться связанными списками?

Какие нужны подпрограммы (возможно уже записанные в памяти, библиотеке компилятора)?

Каким ЯзПр пользоваться?

Конкретные реализации (ответы на указанные вопросы) могут существенно влиять на требования к памяти и на скорость алгоритма, определяющие его эффективность. То есть эффективность программы (алгоритма) имеет две составляющие: память (или пространство) и время. Эти составляющие являются фундаментальными для любых физических систем.

191

Объем памяти и время решения задачи являются важнейшими ресурсными характеристиками ЭВМ. Поэтому алгоритмы часто сравнивают по их значениям.

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

Пусть А – алгоритм для решения некоторого класса задач, а n

– размерность отдельной задачи из этого класса. В общем случае n может быть массивом или длиной вводимой последовательности данных. Определим функцию fA(n) как РАБОЧУЮ ФУНКЦИЮ, дающую верхнюю границу для максимального числа основных операций (сложений, сравнений операций и т.д.), который должен выполнить алгоритм А для решения любой задачи размерности n.

Говорят, что алгоритм А ПОЛИНОМИАЛЬНЫЙ, если fA(n) растет не быстрее, чем полином от n, в противном случае алгоритм А экспоненциальный.

Так вот, если алгоритм получается экспоненциальным, то ЭВМ довольно быстро (при увеличении n) «ЗАДЫХАЕТСЯ», то есть такой алгоритм не очень годится.

Порядок алгоритма полиномиальной сложности обозначается как О(ха) для некоторой переменной х и константы а>1. Существует множество алгоритмов с различными полиномиальными оценками сложности: О(х1) – линейная сложность; О(х2) – квадратичная; О(х3) – кубическая сложность. Частным случаем полиномиальной сложности является логарифмическая сложность О(logax).

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

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

192

n

log2n

n log2n

n2

n3

2n

3n

1

0

0

1

1

2

3

2

1

2

4

8

4

9

4

2

8

16

64

16

81

8

3

24

64

512

256

6561

16

4

64

256

4096

65536

4 107

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

Сложность алгоритма

Число наборов данных, обрабатывае-

 

мых в 1000 раз более мощным ком-

 

пьютером

n

1000,0

n log2n

140,2

n2

31,6

n3

10,0

2n

2,0

n!

1,2

Из табл. видно, что для линейных алгоритмов увеличение скорости работы компьютера в 103 раз приводит к такому же увеличению, а для квадратичной сложности – всего в 30 раз!

Так как около 90 % времени работы программы требуют выполнения повторений (циклов, рекурсий) и только 10 % составляют непосредственные вычисления, то глубина вложенности структур данных играет кардинальную роль, которую надо всегда уменьшать и уметь правильно вычислить.

3.11.Основные алгоритмы построения и модификации структур данных

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

193

ми в предыдущих лекциях структуры данных с алгоритмической точки зрения.

3.11.1. Массивы (последовательное распределение) Рассмотрим преимущества и недостатки использования мас-

сивов. Среди преимуществ отметим следующие:

1.Массивы помогают объединить множества данных в осмысленные группы.

2.Имена массивов с индексами минимизируют потребность в слежении за многими элементами данных с различными именами.

3.Использование индексов обеспечивает непосредственный и автоматический доступ к любому элементу в массиве.

4.Индексация позволяет производить с помощью циклов DO

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

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

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

 

S1

S2

S3

 

 

Sn-1

Sn

 

№ ячейки

1

2= 1+d

3= 1+2d

 

 

n-1=

n=

памяти

 

 

 

 

 

 

 

=ℓ1+(n-2)d

=1+(n-1)d

 

 

 

 

 

 

Так, элемент S1 хранится в ячейке 1, S2 хранится, начиная с ячейки 2=ℓ1+d, S3 хранится, начиная с ячейки 3=ℓ1+2d и т.д., в общем случае i=ℓ1+(i-1)d, где d – число ячеек, требуемых для хранения одного элемента массива. Тем самым последовательности (конечные и бесконечные) являются формальным аналогом рассмотренных нами структур данных.

194

для простых чисел: 1 1 1 0 1 0 1 0 0 0
Если соответствие между i и Si более сложное, то использование характеристического вектора может оказаться очень неэкономичным в смысле времени обработки.
3.11.2. Связанное распределение Неудобство включения и исключения элементов при после-
довательном распределении происходит из-за того, что порядок следования элементов задается неявно требованием, чтобы смежные элементы последовательности находились в смежных ячейках памяти. В результате многие элементы последовательности при включении и исключении должны передвигаться («расталкивать-
ся»).
Информацию о способе упорядочения последовательности можно задать явно с помощью указателей, тогда необходимость в передвижке элементов отпадает. Это так называемое связанное распределение.

Важной разновидностью последовательного распределения является случай, когда такому представлению подвергается подпоследовательность (подмассив) некоторого основного массива. В этом случае можно представить подпоследовательность более удобно, используя характеристический вектор – последовательность нулей и единиц, где i-ый разряд равен 1, если Si принадлежит рассматриваемой последовательности, и нулю в противном случае.

Пусть дана последовательность

 

 

 

 

 

 

Si:

1

2

3

4

5

6

7

8

9

10

характеристи-

 

 

 

 

 

 

 

 

 

 

ческий вектор

 

 

 

 

 

 

 

 

 

 

 

INFO

LINK

ИНФО

СВЯЗЬ

 

ИНФО

СВЯЗЬ

 

ИНФО

СВЯЗЬ

 

 

 

 

 

 

 

 

 

 

 

 

S1

P1=ℓ2

 

S2

P2=ℓ3

Sn-1

Pn-1=ℓn

 

Sn

Pn=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ячейки 1

 

 

2

 

 

n-1

 

 

n

 

памяти

 

 

 

 

 

 

 

 

 

 

195

При связанном распределении каждому элементу Si поставлен в соответствие указатель Pi , отмечающий ячейку, в которой записаны Si+1 и Pi+1. Для этого каждая ячейка (узел, элемент) состоит из двух полей. В поле INFO размещен сам элемент последовательности Si , а в поле LINK - указатель на следующий элемент Si+1. Поскольку для Sn=INFO(n) следующего элемента не существует, мы будем использовать обозначение Pn=LINK(n)= , где - пустой или нулевой указатель. Так как точные значения 1, ℓ2,…, ℓn (адреса ячеек памяти) для нас не существенны, то в более общем виде связанное представление изображается так:

 

 

 

 

 

 

 

 

 

 

 

 

 

S1

 

 

S2

 

Sn-1

 

 

Sn

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

Первый алгоритм будет удалять заданный элемент из связанного списка. Для этого мы ищем ячейку i, у которой ИНФО(i)=3, передвигая указатели PREV и PTR до тех пор, пока такая ячейка не найдена. Затем мы заменяем значение СВЯЗЬ (УКАЗАТЕЛЬ LINK) в ячейке, на которую указывает PREV, на значение СВЯЗЬ в ячейке, на которую указывает PTR.

Algorithm DELETE (удаление). Удаляется ячейка i, у которой INFO(i)=VALUE (искомая переменная) из связанного списка, первая ячейка которого задается переменной FIRST.

196

Шаг 1. [Выбор первой ячейки] Set PTR FIRST; PREV 0.

Шаг 2. [Ячейка пуста?] While PTR 0 do шаг 3od (символ конца конструкции do).

Шаг 3. [Это она?] If INFO(PTR)=VALUE then [Это первая ячейка?]

if PREV=0 then [удалить спереди]

set FIRST LINK(PTR); and STOP

else [удалить изнутри]

set LINK(PREV) LINK(PTR);

and STOP fi (символ конца конструкции if) else [выбор следующей ячейки]

set PREV PTR; PTR LINK(PTR) fi.

Шаг 4. [Не в списке] НАПЕЧАТАТЬ «ЗНАЧЕНИЕ НЕ В СПИСКЕ»; and STOP.

Шаги алгоритма поясняются следующим рисунком.

0

 

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PREV

 

 

PTR

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PREV

 

 

 

PTR

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PREV

 

 

PTR

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

2

 

 

 

3

 

 

 

4

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Блок-схема алгоритма DELETE (УДАЛЕНИЕ) показана на рис. 3.16.

197

Начало

Выбрать первую ячейку

Да

Ячейка пуста?

 

Нет

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Да

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Это

 

 

 

 

 

 

 

 

 

 

 

она?

 

 

 

 

 

 

 

 

 

 

 

Нет

Это пер-

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Да

 

 

 

вая ячей-

 

 

 

Нет

 

 

 

 

Выбор сле-

 

 

 

 

 

ка?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

дующей

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Удалить спе-

 

 

Удалить из-

 

Напечатать

 

 

 

 

реди

 

 

 

нутри

 

«не в списке»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Окончание

Рис. 3.16. Блок-схема алгоритма DELETE (УДАЛЕНИЕ)

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

ОДИН < ДВА < ТРИ < ЧЕТЫРЕ.

198

Этот алгоритм аналогичен алгоритму DELETE (УДАЛЕНИЕ) в том отношении, что при выполнении операции внесения используются указатели PREV и PTR.

Algorithm INSERT (внесение). Внести новую ячейку ROW(РЯД), где INFO(ROW)=VALUE, в упорядоченный связанный список, первая ячейка которого задается в FIRST(ПЕРВЫЙ).

Шаг 1. [Выбор первой ячейки] Set PTR FIRST; PREV 0. Шаг 2. [Ячейка пуста?] While PTR 0 do шаг 3od.

Шаг 3. [Предшествует ли первая ячейка выбранной?] If

 

VALUE

INFO(PTR)

then [вносится спереди?]

 

 

if PREV=0 then [внести новую ячейку спереди]

 

 

set FIRST ROW;

 

 

LINK(ROW) PTR;

 

 

and STOP

 

else [внести новую ячейку внутрь]

 

set LINK(PREV)

ROW;

 

LINK(ROW)

PTR; and STOP fi

else [выбрать очередную ячейку]

 

 

set PREV

PTR; PTR LINK(PTR) fi.

Шаг 4. [Список пуст?] if PREV=0

 

 

then [внести новую ячейку как единственную ячейку в списке]

set FIRST

ROW; LINK(ROW)

0; and STOP

else [внести новую ячейку в конец списка]

set LINK(PREV) ROW; LINK(ROW) 0; and STOP fi.

Шаги алгоритма поясняются следующим рисунком.

199

1

 

 

2

 

 

4

0

 

 

 

 

 

 

 

 

PREV PTR

 

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

2

 

 

4

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PREV

 

 

PTR

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3

1

 

2

 

 

4

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PREV

 

 

PTR

 

 

 

 

 

 

 

 

 

 

3

1

2

4

0

PTR

PREV

3

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

С помощью связанного распределения мы добились большей

200

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]