-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathdijkstra.m
111 lines (104 loc) · 4.13 KB
/
dijkstra.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
function [d pred]=dijkstra(A,u)
% DIJKSTRA Compute shortest paths using Dijkstra's algorithm
%
% d=dijkstra(A,u) computes the shortest path from vertex u to all nodes
% reachable from vertex u using Dijkstra's algorithm for the problem.
% The graph is given by the weighted sparse matrix A, where A(i,j) is
% the distance between vertex i and j. In the output vector d,
% the entry d(v) is the minimum distance between vertex u and vertex v.
% A vertex w unreachable from u has d(w)=Inf.
%
% [d pred]=dijkstra(A,u) also returns the predecessor tree to generate
% the actual shorest paths. In the predecessor tree pred(v) is the
% vertex preceeding v in the shortest path and pred(u)=0. Any
% unreachable vertex has pred(w)=0 as well.
%
% If your network is unweighted, then use bfs instead.
%
% See also BFS
%
% Example:
% % Find the minimum travel time between Los Angeles (LAX) and
% % Rochester Minnesota (RST).
% load_gaimc_graph('airports')
% A = -A; % fix funny encoding of airport data
% lax=247; rst=355;
% [d pred] = dijkstra(A,lax);
% fprintf('Minimum time: %g\n',d(rst));
% % Print the path
% fprintf('Path:\n');
% path =[]; u = rst; while (u ~= lax) path=[u path]; u=pred(u); end
% fprintf('%s',labels{lax});
% for i=path; fprintf(' --> %s', labels{i}); end, fprintf('\n');
% David F. Gleich
% Copyright, Stanford University, 2008-200909
% History
% 2008-04-09: Initial coding
% 2009-05-15: Documentation
if isstruct(A),
rp=A.rp; ci=A.ci; ai=A.ai;
check=0;
else
[rp ci ai]=sparse_to_csr(A); check=1;
end
if check && any(ai)<0, error('gaimc:dijkstra', ...
'dijkstra''s algorithm cannot handle negative edge weights.'); end
n=length(rp)-1;
d=Inf*ones(n,1); T=zeros(n,1); L=zeros(n,1);
pred=zeros(1,length(rp)-1);
n=1; T(n)=u; L(u)=n; % oops, n is now the size of the heap
% enter the main dijkstra loop
d(u) = 0;
while n>0
v=T(1); ntop=T(n); T(1)=ntop; L(ntop)=1; n=n-1; % pop the head off the heap
k=1; kt=ntop; % move element T(1) down the heap
while 1,
i=2*k;
if i>n, break; end % end of heap
if i==n, it=T(i); % only one child, so skip
else % pick the smallest child
lc=T(i); rc=T(i+1); it=lc;
if d(rc)<d(lc), i=i+1; it=rc; end % right child is smaller
end
if d(kt)<d(it), break; % at correct place, so end
else T(k)=it; L(it)=k; T(i)=kt; L(kt)=i; k=i; % swap
end
end % end heap down
% for each vertex adjacent to v, relax it
for ei=rp(v):rp(v+1)-1 % ei is the edge index
w=ci(ei); ew=ai(ei); % w is the target, ew is the edge weight
% relax edge (v,w,ew)
if d(w)>d(v)+ew
d(w)=d(v)+ew; pred(w)=v;
% check if w is in the heap
k=L(w); onlyup=0;
if k==0
% element not in heap, only move the element up the heap
n=n+1; T(n)=w; L(w)=n; k=n; kt=w; onlyup=1;
else kt=T(k);
end
% update the heap, move the element down in the heap
while 1 && ~onlyup,
i=2*k;
if i>n, break; end % end of heap
if i==n, it=T(i); % only one child, so skip
else % pick the smallest child
lc=T(i); rc=T(i+1); it=lc;
if d(rc)<d(lc), i=i+1; it=rc; end % right child is smaller
end
if d(kt)<d(it), break; % at correct place, so end
else T(k)=it; L(it)=k; T(i)=kt; L(kt)=i; k=i; % swap
end
end
% move the element up the heap
j=k; tj=T(j);
while j>1, % j==1 => element at top of heap
j2=floor(j/2); tj2=T(j2); % parent element
if d(tj2)<d(tj), break; % parent is smaller, so done
else % parent is larger, so swap
T(j2)=tj; L(tj)=j2; T(j)=tj2; L(tj2)=j; j=j2;
end
end
end
end
end