Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
algorithms.doc
Скачиваний:
29
Добавлен:
06.12.2018
Размер:
9.73 Mб
Скачать
            1. Алгоритм Дейкстры

n=0; c=a; sc=TRUE; lc=0; backc=NULL //Q0={(a,0, true,NULL)}

Вечный цикл

Для всех вершин v, смежных с

Если sc==FALSE и (lv==+INF или lc+|(c,v)|< lv) то

lv = lc+|(c,v)|; backv=c

l=+INF

Для всех вершин графа v

Если sc==FALSE и lv< l то l = lv; z=v

Если l==+INF то ВЫЙТИ// в графе не осталось элементов

Если z==b то ВЫЙТИ // дошли до конца пути

sz=TRUE; c= z // Qn+1= Qn {(z,l,true)}

            1. Конец вечного цикла

Если после завершения первой части алгоритма l==+INF , то это означает, что от a до b дойти по ребрам невозможно. Иначе, мы можем по ссылкам backw добраться от b до a.

Проанализировав алгоритм для случая планарных графов без кратных ребер и петель, мы сможем заметить, что его можно улучшить. Действительно, при коррекции lv для каждой вершины перебираются все смежные ребра и это происходит ровно один раз. Поэтому суммарное количество операций по коррекции lv не превосходит O(q), где – q количество ребер, а для рассматриваемого случая O(q)= O(p), где – q количество вершин графа.

Допустим, что мы сможем создать структуру данных, содержащую вещественные числа, в которую можно добавлять элементы, удалять из нее минимальный элемент, искать минимум элементов, модифицировать положение элемента при изменении его значения, причем каждая из этих операций должна выполняться за время O(log N), где – N количество элементов, занесенных в данную структуру. Назовем множество, реализованное с помощью указанной структуры данных, P.

На каждом шаге вышеописанного алгоритма мы можем хранить в множестве P ссылки на все элементы, содержащие вершины, смежные с вершинами очередного Qn, которые сами в Qn не содержатся. Заметим, что именно среди этих элементов происходит коррекция lv и поиск минимально lv. На каждом шаге алгоритма Дейкстры мы должны сначала добавить в P ссылки на все элементы, смежные c, при изменении значений lv модифицировать положение соответствующих элементов, а в конце извлечь из P ссылку на элемент с минимальным значением lv. Т.о. алгоритм придет к следующему виду

            1. Алгоритм Дейкстры модифицированный

n=0; c=a; sc=TRUE; lc=0; backc=NULL //Q0={(a,0, true,NULL)}

P={ }

Вечный цикл

Для всех вершин v, смежных с

Если sc==FALSE и lv==+INF то

Добавить ссылку на v в P

Если P пусто то lz =+INF; ВЫЙТИ// в графе не осталось элементов

Для всех вершин v, смежных с

Если sc==FALSE и (lv==+INF или lc+|(c,v)|< lv) то

lv = lc+|(c,v)|; backv=c;

Скорректировать положение ссылки на v в P

Извлечь из P ссылку на минимальный элемент и

поместить минимальный элемент в z

l = lz

Если z==b то ВЫЙТИ // дошли до конца пути

sz=TRUE; c= z // Qn+1= Qn {(z,l,true)}

            1. Конец вечного цикла

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

Итак для случая планарных графов без кратных ребер и петель, в каждом переборе смежных вершин на протяжении всего алгоритма каждое ребро встречается только два раза, поэтому суммарное время работы первого цикла Для всех… равно O(p log p), суммарное время работы второго цикла Для всех… имеет такую же ассимптотику. Наконец, извлечение из P ссылки на минимальный элемент выполняется за время O(log p), а т.к. таких элементов O(p), то суммарное время этих извлечений = O(p log p). Таким образом, доказана следующая

Теорема 1. Для случая планарных графов без кратных ребер и петель алгоритм Дейкстры работает за время O(p2), а модифицированный алгоритм Дейкстры работает за время O(p log p), где p – количество вершин в графе.

До сих пор мы не предъявили реализации структуры данных, содержащей вещественные числа, такой, что она должна уметь выполнять следующие операции:

  • добавлять элемент,

  • удалять минимальный элемент,

  • искать минимум элементов,

  • модифицировать положение элемента при изменении его значения,

причем каждая из этих операций должна выполняться за время O(log N), где – N количество элементов, занесенных в данную структуру.

В качестве подобной структуры данных может выступать пирамида, определенная для сортировки Heapsort. При ее определении мы требовали, чтобы в ее вершине лежал максимальный элемент (исходя из того, что A[i/2] Ai ). Мы можем не менять определения пирамиды, потребовав, чтобы в нее заносились исходные элементы, умноженные на –1, в таком случае в вершине будет храниться минимальный элемент исходного множества (умноженный на –1).

Удалять максимальный элемент из пирамиды за время O(log N) мы научились в алгоритме Heapsort. Находить максимальный элемент за время O(1) можно элементарно – он лежит в первом элементе массива пирамиды. Осталось научиться вставлять новый элемент в пирамиду и корректировать его положение при изменении значения.

Добавление элемента

Пусть дан пирамидально-упорядоченный массив Ai, (i=1,…,N). Требуется добавить к нему еще один элемент Ai+1 и переупорядочить массив. Для этого введем текущий номер элемента в массиве k. В начальный момент положим k= N+1.

Свойство пирамидально-упорядоченности выполняется для всех соответствующих пар элементов, кроме, быть может, пары (k,k/2). Если для этой пары свойство A[k/2] Ak выполняется, то массив пирамидально упорядочен и ничего больше делать не надо. Иначе поменяем местами пару элементов с индексами k и k/2. При этом элемент с индексом k/2 не уменьшится, поэтому поддерево, с него начинающееся, но идущее по другой ветке, чем (k,k/2) останется пирамидально-упорядоченным (т.е., например для четного k, останется верным A[k/2] Ak+1).

Перед обменом местами элементов с индексами (k,k/2), элемент A[k/2] был не меньше всех элементов в поддереве, начинающегося с A[k/2], кроме, быть может, Ak. Поэтому, после обмена местами элементов с индексами (k,k/2), элемент Ak будет не меньше всех элементов в поддереве, начинающегося с Ak. Осталось присвоить k=[k/2], и выполнить те же самые действия для нового k.

Таким образом, мы произведем не более [log N]+1 обменов местами соседних элементов, из чего следует, что процедура добавления элемента в пирамиду может быть произведена за время O(log N).

Корректировка положения элемента

Пусть дан пирамидально-упорядоченный массив Ai, (i=1,…,N). Для текущего элемента в массиве с номером k изменим значение элемента Ak. Требуется переупорядочить массив.

Если Ak A2k и Ak A2k+1, то задача полностью сводится к предыдущей.

Пусть, для определенности, Ak< A2k. Но тогда A[k/2] Ak (т.к. A[k/2] A2k> Ak), из чего получаем, что все элементы из поддерева, начинающегося с k-го элемента массива не превосходят A[k/2] . В этом случае возможно применить процедуру Heapify(A,k,N). Время ее работы O(log N).

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