«Дискретті математика»



бет5/7
Дата21.10.2023
өлшемі445,27 Kb.
#120208
1   2   3   4   5   6   7
Байланысты:
Дийкстра алгоритмі

Дұрыстығын дәлелдеу
a төбесінен v шыңына дейінгі ең қысқа жолдың ұзындығы l(v) болсын. Кез келген z шыңына барған кезде d(z)=l(z)} теңдігі болатынын индукция арқылы дәлелдейік.
Негіз. Алдымен а шыңы барады. Осы сәтте d(a)=l(a)=0
Қадам. Жоғарыға баруды таңдайық
z≠a. Осы сәтте d(z)=l(z) екенін дәлелдейік. Біріншіден, кез келген v шыңы үшін d(v)≥l(v) әрқашан орындалатынын ескеріңіз (алгоритм барлық бар жолдардың ең қысқасынан қысқа жолды таба алмайды). Болсын
P - а-дан z-ге дейінгі ең қысқа жол. Vertex z P нүктесінде және оған кірген жоқ. Демек, P нүктесіндегі ашылмаған шыңдар жиыны бос емес. y P нүктесіндегі бірінші кірмеген шыңы болсын, оның алдындағы x (демек барған). P жолы ең қысқа болғандықтан, оның а-дан х-тен у-ға дейінгі бөлігі де ең қысқа, сондықтан l(y)=l(x)+w(xy).
Индукциялық гипотеза бойынша х шыңына бару сәтінде d(x)=l(x) орындалды, сондықтан у шыңы d(x)+w(xy)=l(x) мәнінен аспайтын белгіні алды. +w(xy)= l(y)}. Демек, d(y)=l(y). Егер z=y болса, онда индуктивті ауысу дәлелденеді. Әйтпесе, енді y емес, z шыңы таңдалғандықтан, белгі z кірмегендер арасында минималды, яғни d(z)≤d(y)=l(y)≤l(z). Мұны d(z)≥l(z)-мен біріктірсек, бізде болады d(z)=l(z), бұл дәлелдеуді қажет етті.
Алгоритм барлық шыңдарға барған кезде аяқталатындықтан, осы кезде d=l барлық шыңдар үшін.


Алгоритмнің күрделілігі
Дийкстра алгоритмінің күрделілігі v шыңын табу әдісіне, сонымен қатар қаралмаған шыңдар жиынын сақтау әдісіне және белгілерді жаңарту әдісіне байланысты. G графындағы төбелер санын n арқылы, ал жиектер санын m арқылы белгілейік.
Ең қарапайым жағдайда, ең аз d[v] төбесін іздеу үшін шыңдардың барлық жиынын іздегенде және d мәндерін сақтау үшін массив пайдаланылса, алгоритмнің орындалу уақыты:
O(n^{2}). Негізгі цикл шамамен n рет орындалады, олардың әрқайсысында минимумды табуға шамамен n амал жұмсалады. Әрбір барған шыңның көршілері арқылы өтетін циклдар m жиектерінің санына пропорционалды бірқатар операцияларды талап етеді (өйткені әрбір жиек осы циклдарда дәл екі рет орын алады және операциялардың тұрақты санын қажет етеді). Осылайша, алгоритмнің жалпы орындалу уақыты O(n^{2}+m), бірақ m≤n(n-1) болғандықтан, ол O(n^{2}).
Сирек Графтар үшін (яғни, олар үшін m n²-ден әлдеқайда аз) қосылмаған шыңдарды екілік үймеде сақтауға болады, ал d[i] мәндерін кілт ретінде пайдалануға болады, содан кейін жою уақыты d[i ] модификация уақыты log n-ге дейін ұлғаятынын ескерсек, Ū шыңы logn болады. Цикл шамамен n рет орындалатындықтан және белгіні өзгерту саны m-ден аспайтындықтан, мұндай іске асырудың орындалу уақыты (nog n+mlog n) болады.
Орташа O(\og n) ішінде жойылатын және орташа O(1) мәнін азайтатын кірмеген шыңдарды сақтау үшін Фибоначчи үйіндісін қолдансақ, онда алгоритмнің орындалу уақыты O(nlog n) болады. +м).









A

B

C

D

E

F

G

H

A

0















B



6













C





14











D







17









E









10







F











25





G













30



H















23

import math

def get_link_V(V, D):
for i, weight in enumerate(D[V]):
if weight > 0:
yield i

def arg_min(T, S):


amin = -1
m = math.inf
for i, t in enumerate(T):
if t < m and i not in S:
m = t
amin = i
return amin

D = (
(0, 6, 0, 0, 0, 0, 0, 0),


(6, 0, 8, 0, 4, 0, 0, 0),
(0, 8, 0, 3, 0, 0, 0, 9),
(0, 0, 3, 0, 7, 8, 0, 0),
(0, 4, 0, 7, 0, 0, 0, 0),
(0, 0, 0, 8, 0, 3, 5, 0),
(0, 0, 0, 0, 0, 5, 0, 0),
(0, 0, 9, 0, 0, 0, 0, 0),
)
N = len(D)
T = [math.inf] * N
V = 0
S = set([V])
T[V] = 0

while V != -1:


for j in get_link_V(V, D):
if j not in S:
w = T[V] + D[V][j]
if w < T[j]:
T[j] = w
V = arg_min(T, S)
if V != -1:
S.add(V)

# А төбесінен барлық басқа төбелерге дейінгі ең қысқа қашықтықтарды басып шығару


for i in range(N):
print(f"Расстояние от узла A до узла {chr(65 + i)} составляет {T[i]}"




Достарыңызбен бөлісу:
1   2   3   4   5   6   7




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет