Dijkatra 迪克斯特拉双栈算术表达式求值算法 Java

本文介绍了一种使用栈实现的表达式求值算法,通过解析输入字符串中的运算符和操作数,并利用两个栈来分别存储它们,从而实现对复杂算术表达式的计算。示例代码演示了如何计算带有括号的算术表达式。
import java.util.Stack;

/**
 * Created by yywang on 2017/1/14.
 */
public class Evaluate {

    static double evaluate(String tmp){
        Stack<String> ops = new Stack<String>();
        Stack<Double> vals = new Stack<Double>();
        for (int i=0; i<tmp.length(); i++){
            String s = String.valueOf(tmp.charAt(i));

            //运算符压入 操作符栈
            if(s.equals("(")) ;
            else if(s.equals("+")) ops.push(s);
            else if(s.equals("-")) ops.push(s);
            else if(s.equals("*")) ops.push(s);
            else if(s.equals("/")) ops.push(s);
            else if(s.equals(")")){
                //遇到右括号开始计算
                String op = ops.pop();
                double v = vals.pop();
                if (op.equals("+")) v = vals.pop() + v;
                if (op.equals("-")) v = vals.pop() - v;
                if (op.equals("*")) v = vals.pop() * v;
                if (op.equals("/")) v = vals.pop() / v;

                vals.push(v);
            }else{
                //数字压入 操作数栈
                vals.push(Double.parseDouble(s));
            }

        }
        return vals.pop();
    }
    public static void main(String[] args) {
        String t = "(1+((2+3)*(4*5)))";
        double ret = evaluate(t);
        System.out.println(ret);
    }
}

输出结果

101.0
<think>好的,我现在要处理用户关于Dijkstra算法的问题。用户想了解这个算法用于计算最短路径的相关信息,包括算法本身、图论中的实现等。首先,我需要回忆一下Dijkstra算法的基本概念和步骤,确保自己理解正确。 Dijkstra算法是由Edsger Dijkstra提出的,用于解决带权有向图的单源最短路径问题。它的核心思想是贪心算法,每次选择距离源点最近的节点,并更新其邻接节点的最短距离。这个算法适用于边权非负的情况,所以如果有负权边,可能需要用其他算法比如Bellman-Ford。 接下来,我需要整理算法的步骤。根据已有的知识,算法通常需要一个距离数组dist,记录源点到各节点的当前最短距离,还有一个visited数组标记节点是否已经确定最短路径。初始化时,源点的距离设为0,其他设为无穷大。然后循环选择未访问节点中距离最小的,更新其邻居的距离,直到所有节点都被访问。 用户提供的引用中,引用[3]提到维护dist和visited数组,引用[1]和[2]说明这是单源最短路径的解决方案,而引用[4]提到Python实现的代码。可能需要参考这些内容来构建回答的结构。 然后,我需要考虑如何将步骤转化为清晰的文字描述,并给出一个具体的例子帮助理解。例如,用一个简单的图来演示算法执行过程,分步骤说明每个节点的处理顺序和距离的更新情况。 实现部分,用户可能希望看到代码示例。根据引用[4],用户提到Python实现的源码,但原引用中的代码可能没有给出。我需要回忆或查找一个典型的Dijkstra算法Python实现,确保使用优先队列来提高效率,因为传统的数组实现在时间复杂度上较高。需要注意的是,代码要正确,并符合用户提供的格式要求,比如使用$...$和$$...$$的数学表达式,以及正确的中文注释。 此外,用户可能关心算法的时间复杂度和优化方法。比如,使用优先队列可以将复杂度从O(V^2)降低到O(E + V log V),其中V是顶点数,E是边数。这里需要明确说明不同实现方式的区别。 还要注意用户提到的系统级指令,比如所有数学表达式用行内格式,独立公式单独成段,中文回答,生成相关问题。检查是否有遗漏的格式要求,比如代码块的正确使用,引用标识的位置是否正确。 最后,生成相关问题需要考虑用户可能的进一步疑问,比如算法适用条件、与其他算法的比较(如Floyd算法)、处理负权边的情况,或者实际应用场景如路由协议、地图导航等。 总结一下,回答的结构应该包括:算法概述、核心思想、详细步骤、具体例子、代码实现、时间复杂度分析、适用条件,最后是相关问题。确保各部分引用正确的引用来源,如步骤部分引用[3],实现代码引用[4],单源最短路径的问题引用[1][2]等。同时,避免使用Markdown格式,保持自然的中文表达,并检查LaTeX语法是否正确。</think>### Dijkstra算法详解 #### 一、算法概述 Dijkstra算法用于求解**带权有向图或无向图**中**单源最短路径**问题,要求所有边权非负[^1]。其核心思想是**贪心策略**,通过逐步扩展已确定最短路径的顶点集,动态更新其他顶点的最短距离[^3]。 #### 二、核心思想与步骤 1. **初始化**: - 定义距离数组$dist[]$,记录源点到各顶点的当前最短距离,初始时$dist[源点] = 0$,其余为$\infty$。 - 定义集合$visited[]$标记顶点是否已确定最短路径。 2. **迭代过程**: - 从$dist[]$中选择未访问的**最小距离顶点**$u$,标记$u$为已访问。 - 遍历$u$的所有邻接顶点$v$,若$dist[v] > dist[u] + w(u,v)$($w$为边的权重),则更新$dist[v]$[^3]。 3. **终止条件**: - 重复上述步骤直到所有顶点被访问。 #### 三、实例演示(以图1为例) 假设源点为A,邻接关系如下: ``` A→B(6), A→C(2) B→D(1) C→B(3), C→D(5) ``` 执行过程: 1. 初始$dist = [A:0, B:∞, C:∞, D:∞]$ 2. 选择A→C(距离2),更新B的距离为$2+3=5$,D为$2+5=7$ 3. 选择C→B(距离5),更新D为$5+1=6$ 最终最短路径:$A→C→B→D$,总权重6。 #### 四、代码实现(Python) ```python import heapq def dijkstra(graph, start): dist = {node: float('infinity') for node in graph} dist[start] = 0 heap = [(0, start)] visited = set() while heap: current_dist, u = heapq.heappop(heap) if u in visited: continue visited.add(u) for v, w in graph[u].items(): if dist[v] > current_dist + w: dist[v] = current_dist + w heapq.heappush(heap, (dist[v], v)) return dist ``` *说明:使用优先队列优化时间复杂度至$O(E + V \log V)$,适用于稀疏图[^4]。* #### 五、关键特性 1. **时间复杂度**: - 基础实现(数组遍历找最小值):$O(V^2)$ - 优先队列优化:$O(E + V \log V)$ 2. **适用条件**:边权必须非负,否则可能无法得到正确结果。 #### 六、与其他算法对比 | 算法 | 类型 | 时间复杂度 | 适用场景 | |-------------|------------|--------------|------------------------| | Dijkstra | 单源 | $O(E+V\log V)$| 无负权边 | | Floyd | 多源 | $O(V^3)$ | 任意权(可含负权) | | Bellman-Ford| 单源 | $O(VE)$ | 含负权边检测负环 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值