python | 算法-最短路径-dijikstra改进算法

写在前面:
我自己用python练习算法与数据结构的典型算法汇总在这里:汇总-算法与数据结构-python版,欢迎翻阅!

1️⃣ 参考链接https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class16/Code06_Dijkstra.java

2️⃣ 所用例子

数据结构

与前章同:python | 算法-图的宽度优先遍历

dijikstra改进算法

class Dijikstra:
    # 改进的dijikstra算法: 利用堆结构
    # 从head出发,所有head能到达的节点,生成到达每个节点的最小路径记录并返回
    # 参考:https://github.com/algorithmzuo/algorithmbasic2020/blob/master/src/class16/Code06_Dijkstra.java
    def dijikstra2(self, first):
        node_heap = NodeHeap()
        node_heap.add_update_ignore(first, 0)
        result = {} # node:distance(first到node的最短距离)
        while not node_heap.is_empty():
            record = node_heap.pop()
            cur = record.node
            cur_dis = record.dis # cur diatance
            for edge in cur.edges:
                node_heap.add_update_ignore(edge.n_to, edge.weight + cur_dis)
            result[cur] = cur_dis

        return result

class NodeHeap:
    def __init__(self):
        self.size = 0
        self.nodes_heap = []
        self.dis_map = {} # distance map
        self.heap_index = {} # heap index map

    def is_empty(self):
        return self.size == 0

    def add_update_ignore(self, node, distance):
        # 如果node已经入堆,更新源点到node的最短距离
        if self.in_heap(node):
            self.dis_map[node] = min(self.dis_map[node], distance)
            # 调整堆 insert heapify
            self.insert_heapify(self.heap_index[node])
        if not self.entered(node):
            self.nodes_heap.append(node)
            self.heap_index[node] = self.size
            self.dis_map[node] = distance
            self.insert_heapify(self.size)
            self.size += 1

    def in_heap(self, node):
        return self.entered(node) and self.heap_index[node] != -1

    def entered(self, node):
        return node in self.heap_index.keys()

    def insert_heapify(self, index):
        while self.dis_map[self.nodes_heap[index]] < self.dis_map[self.nodes_heap[int((index - 1) / 2)]]:
            self.swap(index, int((index-1)/2))
            index = int((index -1) / 2)

    def swap(self, index1, index2):
        self.heap_index[self.nodes_heap[index1]] = index2
        self.heap_index[self.nodes_heap[index2]] = index1
        tmp = self.nodes_heap[index1]
        self.nodes_heap[index1] = self.nodes_heap[index2]
        self.nodes_heap[index2] = tmp

    def pop(self):
        node_record = NodeRecord(node=self.nodes_heap[0], distance=self.dis_map[self.nodes_heap[0]])
        self.swap(0, self.size - 1)
        self.heap_index[self.nodes_heap[self.size-1]] = -1
        self.dis_map.pop(self.nodes_heap[self.size-1])
        self.nodes_heap.pop(self.size - 1)
        self.size -= 1
        self.heapify(0, self.size)
        return node_record

    def heapify(self, index, size):
        left = index * 2 + 1
        while left < size:
            smallest = left + 1 if left + 1 < size and \
            self.dis_map[self.nodes_heap[left+1]] < self.dis_map[self.nodes_heap[left]] \
                else left
            smallest = smallest if self.dis_map[self.nodes_heap[smallest]] < self.dis_map[self.nodes_heap[index]] \
                else index
            if smallest == index: break
            self.swap(smallest, index)
            index = smallest
            left = index * 2 + 1

class NodeRecord:
    def __init__(self, node, distance):
        self.node = node
        self.dis = distance

# test
# 自定义一个无向连通图
m = [[7, 'A', 'B'], [5, 'A', 'D'], [9, 'B', 'D'],
     [8, 'B', 'C'], [7, 'B', 'E'], [5, 'C', 'E'],
     [15, 'D', 'E'], [6, 'D', 'F'], [8, 'E', 'F'],
     [9, 'E', 'G'], [11, 'F', 'G'],
     [7, 'B', 'A'], [5, 'D', 'A'], [9, 'D', 'B'],
     [8, 'C', 'B'], [7, 'E', 'B'], [5, 'E', 'C'],
     [15, 'E', 'D'], [6, 'F', 'D'], [8, 'F', 'E'],
     [9, 'G', 'E'], [11, 'G', 'F']]
generator = GraphGenerator()
graph = generator.createGraph(m)
# 指定出发点
first = graph.nodes['C']
D = Dijikstra()
result = D.dijikstra2(first)
for node in result.keys():
    print(str(first.value)+str(node.value)+':'+str(result[node]))

# 输出
# CC:0
# CE:5
# CB:8
# CF:13
# CG:14
# CD:17
# CA:15
posted @ 2022-10-27 15:09  万国码aaa  阅读(71)  评论(0编辑  收藏  举报