def __init__(self, graph): self.graph = graph self.pred = {} # 搜索结束后从尾顶点开始获取完整路径 self.dist = {} # 存储每个顶点到源点的最短距离 self.priority_queue = PriorityQueue() for node in self.graph.nodes.values(): self.pred[node.key] = -1 self.dist[node.key] = sys.maxsize self.priority_queue.insert(PriorityQueueNode(node.key, self.dist[node.key]))
class MSTPrim(object): def __init__(self, graph: Graph): self.graph = graph self.pred = {} self.keys = {} self.in_queue = {} # tag for node set V, True for V-S, False for S self.priority_queue = PriorityQueue() self.result = [] for node in self.graph.nodes.values(): self.pred[node.key] = -1 self.keys[node.key] = sys.maxsize self.in_queue[node.key] = True self.priority_queue.insert( PriorityQueueNode(node.key, self.keys[node.key])) # 随机选择一个顶点开始 def mst_prim(self, start_node_key): """ :param start_node_key:random choose a node to start """ if start_node_key is None: raise TypeError('Input node keys cannot be None') if start_node_key not in self.graph.nodes: raise ValueError('Invalid start or end node key') self.keys[start_node_key] = 0 # 优先级,按照目标,越小优先级越高 self.priority_queue.decrease_key(start_node_key, self.keys[start_node_key]) while self.priority_queue: mini_node_key = self.priority_queue.extract_min( ).obj # 选出边<u,v>,这一轮出现的是上一个进入S的节点权重最小的邻接节点,即v self.in_queue[mini_node_key] = False curren_node = self.graph.nodes[mini_node_key] # 清除u剩余的邻接节点权重 self.clear_pre_node_weight(curren_node) for node in curren_node.adj_nodes.values(): if self.in_queue[node.key]: weight = curren_node.adj_weights[ node. key] # A->B的权重存储在A的邻接权重中 A.adj_weights: {B.key:weight} if weight < self.keys[node.key]: self.keys[node.key] = weight self.pred[node.key] = mini_node_key self.priority_queue.decrease_key(node.key, weight) self.result.append(curren_node.key) print(self.result) def clear_pre_node_weight(self, curren_node): pre_key = self.pred[curren_node.key] if pre_key > -1: pre_node = self.graph.nodes[pre_key] for node in pre_node.adj_nodes.values(): key = node.key if self.in_queue[key]: self.keys[key] = sys.maxsize self.pred[key] = -1 self.priority_queue.decrease_key(key, self.keys[key])
def __init__(self, graph: Graph): self.graph = graph self.pred = {} self.keys = {} self.in_queue = {} # tag for node set V, True for V-S, False for S self.priority_queue = PriorityQueue() for node in self.graph.nodes.values(): self.pred[node.key] = -1 self.keys[node.key] = sys.maxsize self.in_queue[node.key] = True self.priority_queue.insert( PriorityQueueNode(node.key, self.keys[node.key]))
class Dijkstra(object): def __init__(self, graph): self.graph = graph self.pred = {} # 搜索结束后从尾顶点开始获取完整路径 self.dist = {} # 存储每个顶点到源点的最短距离 self.priority_queue = PriorityQueue() for node in self.graph.nodes.values(): self.pred[node.key] = -1 self.dist[node.key] = sys.maxsize self.priority_queue.insert(PriorityQueueNode(node.key, self.dist[node.key])) def dijkstra(self, start_node_key, end_node_key=None): if start_node_key is None: raise TypeError('Input node keys cannot be None') if start_node_key not in self.graph.nodes: raise ValueError('Invalid start or end node key') self.dist[start_node_key] = 0 # 一旦顶点与起始顶点距离更新,则相应更新优先队列 self.priority_queue.decrease_key(start_node_key, self.dist[start_node_key]) while self.priority_queue: current_min = self.priority_queue.extract_min().obj current_node = self.graph.nodes[current_min] for node in current_node.adj_nodes.values(): weight = current_node.adj_weights[node.key] new_weight = self.dist[current_node.key] + weight if new_weight < self.dist[node.key]: self.dist[node.key] = new_weight self.priority_queue.decrease_key(node.key, new_weight) self.pred[node.key] = current_min # Walk backwards to determine the shortest path: # Start at the end node, walk the previous dict to get to the start node if end_node_key: return self.full_path(end_node_key) def full_path(self, end_node_key): reslut = [] current_node_key = end_node_key while current_node_key != -1: reslut.append(current_node_key) current_node_key = self.pred[current_node_key] return reslut[::-1]
class MSTPrim(object): def __init__(self, graph: Graph): self.graph = graph self.pred = {} self.keys = {} self.in_queue = {} # tag for node set V, True for V-S, False for S self.priority_queue = PriorityQueue() for node in self.graph.nodes.values(): self.pred[node.key] = -1 self.keys[node.key] = sys.maxsize self.in_queue[node.key] = True self.priority_queue.insert( PriorityQueueNode(node.key, self.keys[node.key])) # 随机选择一个顶点开始 def mst_prim(self, start_node_key): """ :param start_node_key:random choose a node to start """ if start_node_key is None: raise TypeError('Input node keys cannot be None') if start_node_key not in self.graph.nodes: raise ValueError('Invalid start or end node key') self.keys[start_node_key] = 0 # 优先级,按照目标,越小优先级越高 self.priority_queue.decrease_key(start_node_key, self.keys[start_node_key]) while self.priority_queue: mini_node_key = self.priority_queue.extract_min().obj self.in_queue[mini_node_key] = False curren_node = self.graph.nodes[mini_node_key] for node in curren_node.adj_nodes.values(): if self.in_queue[node.key]: weight = curren_node.adj_weights[node.key] if weight < self.keys[node.key]: self.keys[node.key] = weight self.pred[node.key] = mini_node_key self.priority_queue.decrease_key(node.key, weight)
def setUp(self): self.priority_queue = PriorityQueue()
class TestPriorityQueue(unittest.TestCase): def tearDown(self): self.priority_queue = None def setUp(self): self.priority_queue = PriorityQueue() def test_priority_queue(self): self.assertEqual(self.priority_queue.extract_min(), None) self.priority_queue.insert(PriorityQueueNode('a', 20)) self.priority_queue.insert(PriorityQueueNode('b', 5)) self.priority_queue.insert(PriorityQueueNode('c', 15)) self.priority_queue.insert(PriorityQueueNode('d', 22)) self.priority_queue.insert(PriorityQueueNode('e', 40)) self.priority_queue.insert(PriorityQueueNode('f', 3)) self.priority_queue.decrease_key('f', 2) self.priority_queue.decrease_key('a', 19) mins = [] while self.priority_queue.array: mins.append(self.priority_queue.extract_min().key) self.assertEqual(mins, [2, 5, 15, 19, 22, 40])