Use python to implement Dijkstra's algorithm

本文介绍了一种迪杰斯特拉算法的具体实现方法,并详细解释了如何通过优先级队列来寻找图中从起点到各个节点的最短路径。此外,还提供了加权图和优先级队列的类定义及使用示例。

The implementation of the Dijkstra's Algorithm:

def dijkstra(g, s):
    from priority_queue import PriorityQueue, less_than

    result = []
    class Record:
        def __init__(self, v, parent = -1, cost = WEIGHT_LIMIT):
            self.vertex = v 
            self.parent = parent 
            self.cost = cost
        def __lt__(self, other):
            return self.cost < other.cost
        def get_key(self):
            return self.vertex
        key = property(get_key)

    n = len(g)
    sequence = [Record(i) for i in range(n)]
    sequence[s].cost = 0
    pq = PriorityQueue(less_than, sequence)
    while pq:
        u = pq.pop()
        for v in g.adj(u.vertex):
            nc = u.cost + v.weight
            try:
                if nc < pq[v.vertex].cost:
                    pq.modify(v.vertex, Record(v.vertex, u.vertex, nc))
            except IndexError:
                pass
        result.append(u)
    return result

def print_shortest_path_tree(result, s):
    def get_shortest_path(dic, v, cache):
        ret = cache[v]
        if len(ret) == 0:
            r = dic[v]
            if r.parent != -1:
                pret = get_shortest_path(dic, r.parent, cache)
                ret = "%s->%s" % (pret, v)
            else:
                ret = str(v)
            cache[v] = ret
        return ret
    n = len(result)
    dic = {result[i].vertex: result[i] for i in range(n)}
    cache = ["" for i in range(n)]
    i = n - 1
    while i >= 0:
        get_shortest_path(dic, i, cache)
        i -= 1
    for i in range(n):
        if i != s:
            print("%s: %s" % (cache[i], dic[i].cost))

The class WeightedGraph:

class WeightedGraph:
    class Edge:
        def __init__(self, v, w):
            self.vertex = v
            self.weight = w
        def __repr__(self):
            return "%s(%s)" % (self.vertex, self.weight)

    def __init__(self, v):
        self.vertices = [None for i in range(v)]
        self.empty_list = []

    def add_edge(self, u, v, w = 1):
        l = self.vertices[u]
        e = WeightedGraph.Edge(v, w)
        if l != None:
            l.append(e)
        else:
            l = [e]
            self.vertices[u] = l

    def __bool__(self):
        return len(self.vertices) > 0
    __nonzero__ = __bool__

    def __len__(self):
        return len(self.vertices)

    def number_of_edges(self):
        e = 0
        for l in self.vertices:
            e += len(l)
        return e

    def adj(self, v):
        l = self.vertices[v]
        if l == None:
            l = self.empty_list
        return l

    def __repr__(self):
        ret = ""
        v = len(self.vertices)
        i = 0
        while i < v:
            if self.vertices[i]:
                if len(ret) > 0:
                    ret += "\n"
                ret += ("%s: %s" % (i, self.vertices[i]))
            i += 1
        return ret

The class PriorityQueue:

from __future__ import print_function

import copy

def less_than(a,  b): return a < b
def big_than(a, b): return a > b

def get_key(v):
    ret = None
    if isinstance(v, int) or isinstance(v, float) or isinstance(v, str):
        ret = v
    elif isinstance(v, list) or isinstance(v, tuple):
        ret = v[0]
    else:
        ret = v.key
    return ret

def sink(sequence, i, comparator, positions):
    n = len(sequence)
    if i >= 0 and i < n:
        while True:
            c = (i + 1) * 2
            r = i
            if c < n and comparator(sequence[c], sequence[r]):
                r = c
            c -= 1
            if c < n and comparator(sequence[c], sequence[r]):
                r = c
            if r != i:
                if positions != None:
                    positions[get_key(sequence[i])] = r
                    positions[get_key(sequence[r])] = i
                sequence[i], sequence[r] = sequence[r], sequence[i]
                i = r
            else:
                break

def rise(sequence, i, comparator, positions):
    n = len(sequence)
    if i >= 0 and i < n:
        while i != 0:
            p = (i - 1) // 2
            if comparator(sequence[i], sequence[p]):
                if positions != None:
                    positions[get_key(sequence[i])] = p
                    positions[get_key(sequence[p])] = i
                sequence[i], sequence[p] = sequence[p], sequence[i]
                i = p
            else:
                break

def make_heap(sequence, comparator):
    n = len(sequence)
    i = 1
    while i < n:
        rise(sequence, i, comparator, None)
        i += 1
    return sequence

class PriorityQueue:
    def __init__(self, comparator, sequence):
        self.comparator = comparator
        self.elements = make_heap(sequence, self.comparator)
        self.positions = {get_key(self.elements[i]): i for i in range(len(self.elements))}

    def __len__(self):
        return len(self.elements)

    def __bool__(self):
        return len(self.elements) > 0
    __nonzero__ = __bool__

    def __repr__(self):
        return str(self.elements)

    def top(self):
        if self.elements:
            return self.elements[0]
        raise IndexError("The priority queue is empty")

    def pop(self):
        ret = None
        n = len(self.elements)
        if n > 0:
            ret = self.elements[0]
            if n > 1:
                self.elements[0] = self.elements[n - 1]
                self.elements.pop(-1)
                sink(self.elements, 0, self.comparator, self.positions)
            else:
                self.elements = []
        else:
            raise IndexError("The priority queue is empty")
        return ret

    def modify(self, key, value):
        i = self.positions.get(key)
        if i != None:
            old_value = self.elements[i]
            self.elements[i] = value
            del self.positions[key]
            self.positions[get_key(value)] = i
            if self.comparator(old_value, value):
                sink(self.elements, i, self.comparator, self.positions)
            else:
                rise(self.elements, i, self.comparator, self.positions)
        else:
            raise IndexError("The specific element %s is not in the priority queue" % key)

    def __getitem__(self, key):
        i = self.positions.get(key)
        if i != None:
            return self.elements[i]
        else:
            raise IndexError("The specific element %s is not in the priority queue" % key)
            
if __name__ == "__main__":
    sequence = [7, 2, 5, 8, 1, 0, 3, 9]
    pq = PriorityQueue(less_than, copy.copy(sequence))
    result = []
    while pq:
        e = pq.pop()
        result.append(e)
    assert result == sorted(sequence)

    pq = PriorityQueue(less_than, copy.copy(sequence))
    pq.modify(0, -1)
    print(pq)
    pq.modify(9, -2)
    print(pq)
    pq.modify(-2, 10)
    print(pq)
    pq.modify(-1, 20)
    print(pq)

这个是完整源码 python实现 Django 【python毕业设计】基于Python的天气预报(天气预测分析)(Django+sklearn机器学习+selenium爬虫)可视化系统.zip 源码+论文+sql脚本 完整版 数据库是mysql 本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后本研究旨在开发一个基于Python的天气预报可视化系统,该系统结合了Django框架、sklearn机器学习库和Selenium爬虫技术,实现对天气数据的收集、分析和可视化。首先,我们使用Selenium爬虫技术从多个天气数据网站实时抓取气象数据,包括温度、湿度、气压、风速等多项指标。这些数据经过清洗和预处理后,将其存储在后端数据库中,以供后续分析。 其次,采用s,将其存储在后端数据库中,以供后续分析。 其次,采用sklearn机器学习库构建预测模型,通过时间序列分析和回归方法,对未来天气情况进行预测。我们利用以往的数据训练模型,以提高预测的准确性。通过交叉验证和超参数优化等技术手段,我们优化了模型性能,确保其在实际应用中的有效性和可靠性。 最后,基于Django框架开发前端展示系统,实现天气预报的可视化。用户可以通过友好的界面查询实时天气信息和未来几天内的天气预测。系统还提供多种图表类型,包括折线图和柱状图,帮助用户直观理解天气变化趋势。 本研究的成果为天气预报领域提供了一种新的技术解决方案,不仅增强了数据获取和处理的效率,还提升了用户体验。未来,该系统能够扩展至其他气象相关的应用场景,为大众提供更加准确和及时的气象服务。
<think>我们注意到用户的问题是关于Prim算法的实现,但Prim算法通常用于求解最小生成树(MST),而不是最短路径。最短路径问题通常使用Dijkstra算法、Bellman-Ford算法等。然而,用户明确提到了Prim算法和最短路径,这可能是一个混淆。 根据引用[2],用户提到了Prim算法用于最小生成树,并给出了一个步骤:顶点6,1,2,3已经被选择,问下一步选择哪个顶点(选项A.0)。但用户当前的问题却是要求实现Prim算法来求解从顶点s到某个顶点的最短路径。 因此,我们需要澄清:Prim算法并不直接用于求解最短路径,而是用于最小生成树。如果用户需要的是最短路径,那么应该使用其他算法,如Dijkstra算法(适用于非负权边)或Bellman-Ford算法(适用于一般情况,可处理负权边但不含负权环)。 但是,考虑到用户可能混淆了术语,或者有特殊要求,我们首先需要明确用户的需求: - 如果用户确实想用Prim算法来求解最短路径,我们需要指出这是不常见的,并解释为什么通常不这样用,然后提供最小生成树的Prim算法实现(因为Prim算法是用于MST的)。 - 如果用户实际上需要的是最短路径算法,那么我们应该提供Dijkstra算法或其他合适的最短路径算法。 由于用户的问题中同时出现了“Prim algorithm”和“shortest path”,并且引用[2]也是关于Prim算法求最小生成树的,引用[1]和[5]则提到了最短路径算法(Floyd-Warshall和DAG的最短路径以及Dijkstra),我们推测用户可能混淆了这两个概念。 因此,我们分两部分回答: 1. 澄清Prim算法用于最小生成树,而最短路径通常使用其他算法。 2. 分别提供Prim算法的实现(用于MST)和Dijkstra算法的实现(用于单源最短路径)供用户参考。 但用户的问题明确要求“Implementation of Prim algorithm for finding the shortest path”,所以我们需要特别说明:Prim算法不是设计用来解决最短路径问题的,但我们可以尝试解释它们之间的区别,并给出Prim算法的标准实现(用于MST)。 然而,有一种观点:在无向图中,最小生成树保证了任意两点之间的路径是唯一的,并且是树中连接这两点的唯一路径,但这条路径并不一定是最短路径(因为最短路径可能不是树中的边,而是通过其他路径的边)。所以,我们不能用Prim算法得到的最短路径来替代最短路径算法。 因此,我们决定: - 首先,解释Prim算法和最短路径算法的区别。 - 然后,提供Prim算法的标准实现(用于MST)。 - 同时,提供Dijkstra算法的实现(用于单源最短路径)作为替代方案。 另外,根据引用[3]和引用[5],我们有一些关于最短路径算法初始化和Dijkstra算法的描述,可以借鉴。 由于用户要求的是实现,我们将提供代码示例(假设是无向图,使用邻接矩阵或邻接表)。 注意:用户没有提供具体的图结构,所以我们用一般化的方式实现。 步骤: 1. 解释Prim算法和最短路径的区别。 2. 实现Prim算法(最小生成树)。 3. 实现Dijkstra算法(单源最短路径)。 我们使用邻接矩阵或邻接表来表示图。为了通用性,这里使用邻接表。 另外,引用[4]是一篇关于最小生成树的论文,我们可以引用它作为Prim算法的背景。 最后,生成相关问题。 </think> ### Prim算法与最短路径问题的澄清 首先需要明确:**Prim算法用于求解最小生成树(MST),而非最短路径**。最小生成树要求连接所有顶点且总权重最小,但不保证任意两点间的路径最短(最短路径问题需用Dijkstra等算法)。若您需要从顶点 $s$ 到特定顶点的最短路径,应使用**D邻克斯特拉算法(Dijkstra)**(适用于非负权边)。 以下分别提供Prim算法(MST)和Dijkstra算法(最短路径)的实现: --- ### 1. Prim算法实现(最小生成树) **算法步骤**: 1. 初始化:选定起点 $s$,将其加入MST集合 $Y$,初始化距离数组 $\lambda[v]$($v$ 到 $Y$ 的最小边权),$\lambda[s] = 0$[^3]。 2. 迭代:每次选择 $\lambda[v]$ 最小的顶点 $v \notin Y$ 加入 $Y$,并更新 $v$ 邻接点的 $\lambda$ 值。 3. 终止:所有顶点加入 $Y$ 时结束。 **Python实现**(邻接表表示无向图): ```python import heapq def prim(graph, start): n = len(graph) lambda_arr = [float('inf')] * n # λ[v] 初始化为无穷大 lambda_arr[start] = 0 heap = [(0, start)] # 最小堆: (λ[v], v) in_mst = [False] * n # 标记顶点是否在MST中 parent = [-1] * n # 记录MST的父节点 while heap: _, u = heapq.heappop(heap) if in_mst[u]: continue in_mst[u] = True for v, weight in graph[u]: if not in_mst[v] and weight < lambda_arr[v]: lambda_arr[v] = weight parent[v] = u heapq.heappush(heap, (weight, v)) return parent # 返回MST的父节点关系 ``` **示例调用**: ```python # 图示例(邻接表):graph[u] = [(v1, w1), (v2, w2), ...] graph = [ [(1, 2), (2, 4)], # 顶点0的邻接边 [(0, 2), (2, 1), (3, 3)], # 顶点1的邻接边 [(0, 4), (1, 1), (3, 5)], # 顶点2的邻接边 [(1, 3), (2, 5)] # 顶点3的邻接边 ] mst_parent = prim(graph, 0) # 从顶点0生成MST print("MST父节点关系:", mst_parent) # 输出: [-1, 0, 1, 1] 表示树结构 0→1→2, 0→1→3 ``` --- ### 2. Dijkstra算法实现(单源最短路径) **适用场景**:从顶点 $s$ 到图中任意顶点的最短路径(要求边权非负)。 **算法步骤**: 1. 初始化:$\lambda[s] = 0$,其他 $\lambda[v] = \infty$[^3]。 2. 迭代:每次选择 $\lambda[v]$ 最小的未访问顶点 $u$,松弛其邻接边(若 $\lambda[u] + w(u,v) < \lambda[v]$,则更新 $\lambda[v]$)。 **Python实现**: ```python import heapq def dijkstra(graph, start): n = len(graph) dist = [float('inf')] * n # s到各点的最短距离 dist[start] = 0 heap = [(0, start)] # 最小堆: (dist[v], v) while heap: d_u, u = heapq.heappop(heap) if d_u != dist[u]: continue for v, w in graph[u]: new_dist = dist[u] + w if new_dist < dist[v]: dist[v] = new_dist heapq.heappush(heap, (new_dist, v)) return dist # 返回s到所有顶点的最短距离 ``` **示例调用**(同前图): ```python shortest_paths = dijkstra(graph, 0) print("从顶点0出发的最短路径:", shortest_paths) # 输出: [0, 2, 3, 5] ``` --- ### 关键区别 | **算法** | 目标 | 输出结构 | 边权要求 | |------------|--------------------|----------------|--------------| | **Prim** | 最小生成树 | 树(连接所有点)| 无限制 | | **Dijkstra**| 单源最短路径 | 路径(源点到其他点)| 非负权边 | > ⚠️ 若需处理负权边或环,请改用**Bellman-Ford算法**;若为有向无环图(DAG),可用**拓扑排序+松弛**($O(V+E)$)[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值