Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
TA1_2.DOC
Скачиваний:
11
Добавлен:
02.11.2018
Размер:
444.42 Кб
Скачать

4) Представление в виде графа.

Обозначим : G = < V, E > неориентированный граф,

G = < V, A > ориентированный.

Пусть p = V, q = E.

a) Матрица смежности

Если граф без кратных ребер и петель, то A: array [ 1..p, 1..p] of 0..1.

Время, необходимое для определения наличия ребра, O( 1 ).

Недостатки:

1) Размер матрицы по памяти  O( p2)

2) Начальное заполнение требует времени O( p2), что сводит на нет алгоритмы сложности

O( p ) при работе с графами, содержащими только O ( p ) ребер.

б) Списки смежности.

Определение.

Списком смежности для узла v называется список всех узлов w, смежных с v.

Граф можно представить с помощью p списков смежностей, по одному для каждого узла.

Пример:

2

Размер требуемой памяти O ( p + q).

Представлением с помощью списков смежностей часто пользуются когда q << p2.

в) Деревья

Определение.

Дерево  это связный ациклический граф.

Представление двоичных деревьев:

1. В виде двух массивов: LeftSon и RightSon. Пусть узлы двоичного дерева занумерованы

целыми числами 1..n.

LeftSon [ i ] = j тогда и только тогда, когда узел с номером j является левым сыном узла с номером i. LeftSon [ i ] = 0, если у узла i нет левого сына. RightSon [ i ] определяется аналогично.

Хорошо для небольших деревьев.

§ 2. “Разделяй и властвуй”.

Для решения той или иной задачи ее часто разбивают на части, находят их решения и затем из них получают решение всей задачи. Этот прием ( Divide & Conque ) , особенно если его применять рекурсивно, часто приводит к эффективному решению задачи, подзадачи которой представляют собой ее меньшие версии.

Пример 1.

Задача о нахождении наибольшего и наименьшего элементов множества S, S = n.

Пусть n = 2k.

1) Будем искать наибольший и наименьший элементы по отдельности.

Процедура Max находит наибольший элемент множества S, произведя n-1 сравнений его элементов.

procedure Max

begin

s0 = произвольный элемент из S;

MAX  x0;

for ( sS \ { x0 } ) do

if x > Max then Max  x;

end;

Аналогично можно найти наименьший элемент из остальных n - 1 элементов, произведя n - 2 сравнений.

Итак, для нахождения наибольшего и наименьшего элемента множества при n  2 потребуется 2n - 3 сравнений.

2) “Разделяй и властвуй”.

( int , int ) procedure MAXMIN ( S )

begin

if ( ||S|| == 2) then return (MAX( a, b), MIN(a, b)); else

begin

S = S1  S2; /* || S1 ||  || S2 || */

(max1, min1) = MAXMIN ( S1);

(max2, min2) = MAXMIN ( S2);

M: return (MAX ( max1, max2 ), MIN ( min1, min2 ));

end;

end;

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

Пусть T( n )  число сравнений в процедуре MAXMIN, чтобы найти наибольший и наименьший элемент n-элементного множества.

T( 2 ) = 1

Если n > 2, то T( n ) - общее число сравнений, произведенных в двух вызовах процедуры MAXMIN, работающей на множествах размера n/2, и еще два сравнения в строке с меткой M.

Итак,

То есть T ( n ) = 3/2 n-2.

Можно показать, что для одновременного нахождения наибольшего и наименьшего элементов

n-элементного множества надо сделать не менее 3/2 n-2 сравнений его элементов. Следовательно, алгоритм процедуры MAXMIN оптимален в смысле числа сравнений между элементами из S, когда n = 2k.

В примере 1 прием “Разделяй и властвуй” позволил уменьшить число сравнений в фиксированное число раз. Но для рекурсии требуется стек, поэтому в памяти мы проиграли.

Пример 2. Умножение n-разрядных двоичных чисел.

  1. Традиционный метод ( умножение “в столбик”) требует OБ( n2) битовых операций.

  2. Следующий алгоритм типа “разделяй и властвуй” требует  O ( n log 3).

Пусть n = 2k.

x, y - два n-разрядных числа.

Разобьем x и y на две равные части.

Если рассматривать каждую из этих частей как ( n/2 )-разрядное число, то можно представить произведение чисел x и y в виде

xy = ( a2 n/2 + b) ( c2 n/2 + d) = ac2n + ( ad + bc ) 2n/2 + bd.

Это равенство дает следующий способ вычисления z = xy:

begin

u  ( a + b) * ( c + d );

va * c;

wb * d;

z v * 2n + ( u - v - w ) * 2 n/2 + w;

end;

Будем считать, что числа a + b и c + d состоят из (n/2) разрядов. Изложенная схема для умножения n-разрядных чисел требует только трех умножений (n/2)-разрядных чисел и нескольких сложений и сдвигов. Для вычисления u, v, w можно применять эту программу рекурсивно. Сложения и сдвиги занимают OБ( n ) времени. Следовательно, временная сложность умножения двух n-разрядных чисел ограничена сверху функцией

a, n=1 (*)

T (n) =

3T (n/2) + an , n > 1

где a - постоянная, отражающая сложение и сдвиги.

Можно показать, что T ( n ) = 3an log 3 - 2an.

ММИ по n, где n - степень числа 2.

1. Базис

n = 1 – тривиально.

2. Пусть T ( n ) = 3anlog 3 - 2kn удовлетворяет () при n = m.

Тогда T ( 2m ) = 3T ( m ) + 2am = 3[ 3anlog3 - 2an ] + 2am = 3a(2m)log3 - 2a ( 2m ).

Таким образом , T ( n ) удовлетворяет () и при n = 2m.

Отсюда следует, что T ( n )  3anlog3.

Учтем, что числа a, b, c, вообще говоря, имеют n/2+1 разрядов. Поэтому произведение (a+b)(c+d) нельзя вычислить непосредственным применением нашего алгоритма к задаче размера n/2.

Запишем :

a + b = a12n/2 + b1, где a1 = 0 или 1 .

c + d = c12n/2 + d1, где c1 = 0 или 1.

Тогда

( a + b )( c + d ) = a1 c12n + (a1d1 + b1 c1 ) 2n/2 + b1d1. ()

Слагаемое b1d1 вычисляется с помощью рекурсивного применения нашего алгоритма умножения к задаче размера n/2. Остальные умножения в () можно сделать за время OБ (n), так как они содержат в качестве одного из аргументов либо единственный бит a1 или c1, либо степень числа 2.

При анализе рекурсивных алгоритмов типа “ разделяй и властвуй ” часто возникают рекуррентные уравнения следующего вида

() - это общая рекурсивная формула при разбиении задачи на a подзадач в c раз меньше, причем слагаемое bn - линейное время на слияние.

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