python实现:dijkstra算法的堆实现与循环桶实现

0.测试数据

'''test-1.txt'''
1
2
1 2 1
1
2

'''test-2.txt'''
282
100
1 2 10
2 3 7
3 4 7
4 5 8
5 6 9
6 7 9
7 8 8
8 9 1
9 10 9
10 11 7
11 12 9
12 13 10
13 14 9
14 15 4
15 16 7
16 17 2
17 18 8
18 19 5
19 20 10
20 21 3
21 22 1
22 23 9
23 24 3
24 25 8
25 26 9
26 27 5
27 28 5
28 29 2
29 30 8
30 31 7
31 32 10
32 33 5
33 34 2
34 35 6
35 36 10
36 37 8
37 38 2
38 39 4
39 40 6
40 41 8
41 42 4
42 43 7
43 44 7
44 45 8
45 46 10
46 47 2
47 48 10
48 49 7
49 50 1
50 51 4
51 52 9
52 53 5
53 54 2
54 55 5
55 56 6
56 57 1
57 58 4
58 59 2
59 60 5
60 61 5
61 62 5
62 63 1
63 64 1
64 65 9
65 66 5
66 67 7
67 68 10
68 69 4
69 70 4
70 71 3
71 72 2
72 73 3
73 74 2
74 75 4
75 76 5
76 77 2
77 78 2
78 79 1
79 80 8
80 81 9
81 82 5
82 83 4
83 84 6
84 85 7
85 86 4
86 87 3
87 88 10
88 89 9
89 90 2
90 91 5
91 92 1
92 93 9
93 94 4
94 95 10
95 96 6
96 97 6
97 98 2
98 99 8
99 100 9
45 93 7
65 69 5
68 76 8
10 94 4
22 59 6
88 95 4
89 98 7
13 72 5
66 90 8
47 72 4
82 88 1
26 99 6
10 31 10
81 87 4
80 96 8
65 84 6
89 91 6
30 50 9
20 35 1
40 73 9
66 76 4
58 91 7
32 56 10
36 99 4
76 95 3
56 85 8
1 38 1
54 60 4
39 80 1
18 98 4
5 48 7
59 91 2
2 68 10
42 78 3
12 59 10
83 95 5
1 16 10
54 67 2
43 64 4
76 81 3
7 76 5
48 52 10
77 82 8
53 94 5
79 95 10
21 80 5
24 38 2
50 56 3
65 97 8
51 88 3
35 84 4
94 98 10
43 57 8
22 96 7
1 12 7
44 68 3
60 63 4
63 99 7
95 99 1
68 87 9
47 83 1
21 72 8
28 43 7
42 44 6
37 48 10
87 99 7
12 15 6
52 69 3
33 88 8
1 40 2
20 67 10
43 95 3
57 98 3
78 81 6
4 99 7
14 55 5
73 93 3
27 94 3
53 57 2
62 77 1
68 82 10
12 99 1
78 92 3
76 93 9
25 55 4
22 48 1
81 83 9
33 65 9
14 86 2
57 82 1
80 90 6
19 60 9
55 71 3
12 51 4
94 96 6
2 98 4
45 70 9
25 93 7
83 99 5
4 81 7
36 59 4
62 68 7
12 97 3
11 66 7
38 67 6
3 31 6
84 94 10
24 78 5
52 99 7
21 75 6
30 98 2
36 76 4
10 84 4
42 66 9
4 51 10
91 94 6
4 36 6
10 21 7
28 74 1
72 80 10
62 84 8
45 80 6
35 60 2
34 40 6
76 79 7
70 92 7
81 90 9
62 64 8
82 99 6
36 93 4
37 86 3
26 94 10
36 87 10
31 61 4
34 53 3
18 21 6
70 76 5
13 58 2
67 83 6
92 98 9
40 80 4
76 99 6
31 49 9
71 79 5
19 63 2
84 86 8
42 72 9
47 69 2
74 93 3
97 99 2
74 86 2
82 92 8
37 68 6
25 89 1
68 88 5
9 66 2
20 93 2
72 96 7
14 73 7
26 59 1
43 58 3
87 92 4
83 88 8
23 31 10
73 87 3
9 89 5
80 92 10
5 45 1
93 99 7
27 80 10
50 78 3
52 88 5
19 54 8
52 83 4
54 98 1
56 75 6
46 70 5
66 73 1
54 85 3
60 77 4
27 63 2
59 69 8
45 59 2
1
100

1.堆实现

'''graphheap.py'''
class Vertex(object):
    
    def __init__(self,name):
        self.min_distance = None
        self.name = name
        self.parent = None
        self.adjacents = []
    
    def __eq__ (self,other):
        return True
    
    def __lt__(self,other):
        return True


class WDGraph(object):
    
    def __init__(self):
        self.VertexNumber = 0
        self.EdgeNumber = 0
        self.VertexSet = {}
        self.origin = None
        self.destn = None

    def generate_graph(self,p,v,w):
        if not p in self.VertexSet:
            self.VertexSet.setdefault(p,Vertex(p))
            
        if not v in self.VertexSet:
            self.VertexSet.setdefault(v,Vertex(v))

        self.VertexSet[p].adjacents.append((w,self.VertexSet[v]))  

         


'''Dijstrak_heap.py'''

import heapq
import string
from graphheap import *


def main():

    Graph = initial_graph()

    S = list(Graph.origin.name)
    CS_Heap = []
    
    for w,adj in Graph.origin.adjacents:
        adj.min_distance = w 
        adj.parent = Graph.origin
        CS_Heap.append((adj.min_distance,adj))

    heapq.heapify(CS_Heap)
    
    while (not Graph.destn.name in S) or CS_Heap:
        Nearest = heapq.heappop(CS_Heap)[1]
        S.append(Nearest.name)

        if Nearest.adjacents:
            for w,adj in Nearest.adjacents:
                distance = w+Nearest.min_distance
            
                if adj.min_distance is None:
                    adj.min_distance = distance
                    adj.parent = Nearest 

                    heapq.heappush(CS_Heap,(adj.min_distance,adj))
                    
                elif distance < adj.min_distance:
                    index = CS_Heap.index((adj.min_distance,adj))
                    
                    adj.min_distance = distance
                    adj.parent = Nearest 

                    CS_Heap[index] = CS_Heap[-1] 
                    heapq._siftup(CS_Heap,index)
                    CS_Heap.pop()

                    heapq.heappush(CS_Heap,(adj.min_distance,adj))
    
    if not Graph.destn.name in S:
        print("{} cannot reach {}".format(Graph.origin.name,Graph.destn.name))
    else:
        print(Graph.destn.min_distance)
        
        node = Graph.destn
        path = list()
        while not node is None:
            path.append(node.name)
            node = node.parent
        
        path.reverse()
        print(path) 


def initial_graph():
    Graph = WDGraph()

    with open('test-1.txt','r') as f:
        Graph.EdgeNumber = int(f.readline().strip())
        Graph.VertexNumber = int(f.readline().strip())

        for i,line in enumerate(f.readlines()):
            if  i == Graph.EdgeNumber:
                Graph.origin = line.strip()
            elif i == Graph.EdgeNumber + 1:
                Graph.destn = line.strip()
            else:
                p,v,w = line.strip().split()
                Graph.generate_graph(str(p),str(v),int(w))
        
        
        Graph.origin = Graph.VertexSet[Graph.origin]
        try: 
            Graph.destn = Graph.VertexSet[Graph.destn]
        except:
            print("{} cannot reach {}".format(Graph.origin.name,Graph.destn))
            exit()
            
        Graph.origin.min_distance = int(0)
    
    return Graph
   

if __name__ == "__main__":
    main()

2.循环桶实现

'''graphcbucket.py'''

class WDGraph(object):
    
    def __init__(self):
        
        self.maxedge = 0 
        self.EdgeNumber = 0
        self.VertexNumber = 0
        self.orgin = None
        self.destn = None 
        self.distance = {}  #record the min_distance
        self.adjencets = {} #key is parent, value is a adj list
         
    def generate_graph(self,p,v,w):

        if self.maxedge < w:
            self.maxedge = w
        
        if not p in self.adjencets:
            self.adjencets.setdefault(p,[(w,v)])
        else:
            self.adjencets[p].append((w,v))

        self.adjencets.setdefault(v,[])

        self.distance.setdefault(p,None)
        self.distance.setdefault(v,None)


class LoopBucket(object):

    def __init__(self,maxedge):
        
        self.pointer = 0
        self.VertexNum = 0
        self.cyclebase = maxedge+1
        self.Bucket = [ [] for i in range(0,self.cyclebase)]
    
    def join(self,distance,parent,vertex):
        
        index = distance % self.cyclebase
        self.Bucket[index].append((distance,parent,vertex))
        self.VertexNum += 1
    
    def popmin(self):

        while not self.Bucket[self.pointer]:
            self.pointer = (self.pointer+1) % self.cyclebase
        
        self.VertexNum -=1
        return self.Bucket[self.pointer].pop()

    def isEmptyBucket(self):
        if self.VertexNum == 0:
            return True
        else:
            return False
    

    
'''dijstrak_cbucket.py'''

import string
from graphcbucket import *

def main():
    Graph = initial_graph()
    Bucket = LoopBucket(Graph.maxedge)
    path = []
    CurrentSet = {} #key is vertex's name,value is its parent
    distance = 0
    parent = None
    Bucket.join(distance,parent,Graph.origin)

    while not (Graph.destn in CurrentSet.keys() and Bucket.isEmptyBucket()):
        Closest_dist,Closest_parent,Closest_name = Bucket.popmin()
         
        if not Closest_name in CurrentSet.keys():
            CurrentSet.setdefault(Closest_name,Closest_parent)
            
            #if the node has adj
            if Graph.adjencets[Closest_name]:
                for weight,adj_name in Graph.adjencets[Closest_name]:
                    distance = Closest_dist + weight
                
                    if Graph.distance[adj_name] is None:
                        Graph.distance[adj_name] = distance
                        parent = Closest_name
                        Bucket.join(distance,parent,adj_name)

                    elif Graph.distance[adj_name] > distance:
                        Graph.distance[adj_name] = distance
                        parent = Closest_name
                        Bucket.join(distance,parent,adj_name)
    
    if not Graph.destn in CurrentSet.keys():
        print("{} cannot reach {}".format(Graph.origin,Graph.destn))
    else:
        print(Graph.distance[Graph.destn])
        
        node = Graph.destn
        path = list()
        while not node is None:
            path.append(node)
            node = CurrentSet[node]
        
        path.reverse()
        print(path) 
    
            
def initial_graph():
    Graph = WDGraph()

    with open('test-3.txt','r') as f:
        Graph.EdgeNumber = int(f.readline().strip())
        Graph.VertexNumber = int(f.readline().strip())

        for i,line in enumerate(f.readlines()):
            if  i == Graph.EdgeNumber:
                Graph.origin = line.strip()
            elif i == Graph.EdgeNumber + 1:
                Graph.destn = line.strip()
            else:
                p,v,w = line.strip().split()
                Graph.generate_graph(str(p),str(v),int(w))

        Graph.distance[Graph.origin] = int(0)

    return Graph


if __name__ == "__main__":
    main()

你可能感兴趣的:(课程实验)