Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the shortest path of Dijkstra algorithm by python3

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

Today, I would like to share with you how python3 to achieve the shortest path of Dijkstra algorithm related knowledge, detailed content, clear logic, I believe that most people still know too much about this knowledge, so share this article for your reference, I hope you will learn something after reading this article, let's take a look at it.

Problem description

Problem: according to the weight of each edge, find out the shortest path and the length of the shortest path from the starting point s to each other vertex.

Note: do not consider the case that the weight is negative, otherwise there will be the problem of negative circle.

S: starting point

V: the vertices currently analyzed and processed by the algorithm

W: the vertex adjacent to v

Dv Dempv dv: the distance from s to v

Dw Dempw dw: the distance from s to w

Cv,w c _ {vdepartment w} cv,w: the weight of the edge from vertex v to vertex w

Analysis of problems

The Dijkstra algorithm is carried out in stages, which is the same as the unauthorized shortest path algorithm (first dealing with vertices with distance 0, then vertices with distance 1, and so on), finding the smallest distance first.

At each stage, the Dijkstra algorithm selects a vertex v, which has the smallest dv diterv dv among all unknown vertices, and the algorithm declares that the shortest path from s to v is known. The rest of the phase is the work of updating w's dv dv (distance) and pv pairv pv (previous vertex) (or probably not).

At every stage of the algorithm, it is handled like this:

[0.5] in the case of dw dw= dw= infty ∞, set dw=dv+1 d_w=d_v+1 dw=dv+1 (the shortest path without authority)

[1] if dw dancw dw= ∞ infty ∞ is authorized, then set dw=dv+cv,w dwelling dwelling vault c _ {vmeme w} dw=dv+cv,w

[2] if dw Dempw dw! = ∞ infty ∞, start to analyze: if the path from vertex v to vertex w is a little shorter than the original path, then w needs to be updated, otherwise w will not be updated. That is, it satisfies d v + c v, w

< d w d_v+c_{v,w} v 3 v_1=>

Vroom4 = > vroom3 v1 = > v4 = > v3

In fact, the above analysis is the idea of the algorithm for finding the shortest path: after each vertex object is processed into a data change table, the shortest path can be obtained by backtracking the pv v PV value of any vertex vi v vi.

Code implementation

Paper will sleep shallow, never know the matter want to practice! Use python3 to implement the function.

This article mentioned that priority queues will be used to find the vertices with the smallest dist among the unknown vertices. There are already well-implemented priority queues using python. However, the error reported in the experiment is as follows:

The less than comparison operator is not supported for Vertex instances. So you need to implement the _ _ lt__ method of the Vertex class. Let's popularize science:

Method name comparison operator meaning _ _ eq__==equal__lt__=greater and equal

Unfortunately, the priority queue from queue import PriorityQueue that comes with the python library does not meet the needs of this article. When the element of PriorityQueue is an object, the class of the object is required to implement the _ _ lt__ function. When adding elements to the priority queue, heap sorting is used internally. The characteristic of heap sorting is that the first element of each heap (and each child heap) is always the smallest element. The key point is that after the heap is established, the heap has recorded the size relationship of each element when the heap was created. After creating the priority queue, the structure of the heap will certainly not change. So this heap sorting causes the sorting to be one-time, and if the properties of an object change later, the heap structure will not change accordingly.

In other words, the priority queue we want is certainly not the priority queue provided by the system, because we want to support the change of the heap caused by the member modification of the variable object, there are three solutions, 1. Internal use of the heap sorting heap, at least to support, delete any node and add node operations (because these two steps can achieve the effect of modification) 2. This internal heap, when performing the dequeue operation, examine which node has the modification operation, then change the heap to the correct shape, and then leave the team 3. Maintain a list, sort and descend, and then each time you change the value of a variable object, you bubble or binary search to find the location (because everything else has been sorted, only it is not in the correct place), and then list.pop (), but the third plan is what I thought of later, so the following code is not implemented in this way, readers can try, it must be faster than traversing all each time.

It should be said that there may be no need for queues. We may only need a list or set to store v, change its dist casually before leaving the team, iterate through the vi of the smallest dist when we leave the team, and then delete the vi. Because the dist of vi is changing all the time, and the requirements are special, but there is no need to build a special wheel (it feels difficult to build either). Although the time complexity may be a little high, the code is simple.

Heap sorting in priority queues

The failure code is as follows: the dist of the three node objects is infinite. If all three objects enter the queue, and then change the dist of v3 to 0, the desired effect is to go out of line v3, but out of line is v1. The reasons are as follows:

From queue import PriorityQueueclass Vertex: # Vertex class def _ _ init__ (self,vid,dist): self.vid = vid self.dist = dist def _ lt__ (self,other): return self.dist < other.dist v1=Vertex (1 inf' ('inf')) v2=Vertex (2 inf' (' inf')) v3=Vertex (3 inf') vlist = [v1v2=Vertex () for i in range (0) Len (vlist): q.put (VList [I]) v3.dist = 0print ('vid:',q.get () .vid) # the result is vid: 1

And if you change the dist before joining the team, you can get out of the team correctly.

V3.dist = 0for i in range (0Len (vlist)): q.put (VList [I]) # the result is vid: 3 use set instead of priority queue class Vertex: # vertex class def _ _ init__ (self,vid,outList): self.vid = vid# outgoing edge self.outList = outList# list of vertices pointed to by the outgoing edge It can also be understood that the adjacency table self.know = False# defaults to false self.dist = float ('inf') # s distance to that point, and defaults to infinity self.prev = the id of the last vertex The default is 0 def _ eq__ (self, other): if isinstance (other, self.__class__): return self.vid = = other.vid else: return False def _ hash__ (self): return hash (self.vid) # create vertex object v1=Vertex (1, [2jue 4]) v2=Vertex (2, [4jue 5]) v3=Vertex (3, [1je 6]) v4=Vertex (4, [3m 5m 6J 7]) v5=Vertex (5) [7]) v6=Vertex (6, []) v7=Vertex (7, [6]) # weight of storage edge edges = dict () def add_edge (front,back,value): edges [(front,back)] = valueadd_edge (1) add_edge (1) add_edge (3) add_edge (4) add_edge (2) add_edge (4) add_edge (3) add_edge (4) 6) add_edge (4) 4) add_edge (7pence6) add_edge (5pence7) # create an array of length 8 To store vertices, 0 index element does not store vlist = [False,v1,v2,v3,v4,v5,v6,v7] # use set instead of priority queue The main reason for choosing set is that set has a convenient remove method vset = set ([v1Gravity v2recitation v3recoveryv5Powerv6recoverv7]) def get_unknown_min (): # this function replaces the outgoing operation of the priority queue the_min = 0 the_index = 0 j = 0 for i in range (1) Len (vlist): if (VList [I] .know is True): continue else: if (junk 0): the_min = VList.Dist the_index = I else: if (VList.Dist < the_min): the_min = vlist [ I] .dist the_index = I j + = 1 # at this time, we have found out who the smallest element is unknown vset.remove (vlist [the _ index]) # is equivalent to performing the outgoing operation return [the _ index] def main (): # set v1 to vertex v1.dist = 0 while (len (vset)! = 0): V = get_unknown_min () print (v.vid V.distjold v.outList) v.know = True for w in v.outList:#w is the index if (vlist [w] .know is True): continue if (vlist[ w] .Dist = = float ('inf')): VList.Dist = v.dist + edges [(v.vid) W)] vlist [w] .prev = v.vid else: if ((v.dist + edges [(v.vid.w)])

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report