1.具体步骤

1)初始化两个栈:运算符栈s1和储存中间结果的栈s2;
2)从左至右扫描中缀表达式;
3)遇到操作数时,将其压s2;
4)遇到运算符时,比较其与s1栈顶运算符的优先级:
     (1)如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
     (2)否则,若优先级比栈顶运算符的高,也将运算符压入s1;
     (3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;
5)遇到括号时:
     (1)如果是左括号“(”,则直接压入s1
     (2)如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6)重复步骤2至5,直到表达式的最右边
7)将s1中剩余的运算符依次弹出并压入s2
8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

2.思路分析

3.代码实现

 /// <summary>
/// 字符串转中缀表达式的List
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
public static List<string> ToInfixExpression(string expression)
{
List<string> list = new List<string>(); int index = ; string str = ""; do
{ //48-57ASCII码代表的是0-9 如果不是0-9直接入链表
if (expression[index] < || expression[index] > )//ascii编码
{
list.Add("" + expression[index]); index++;
}
else
{
str = ""; //多位数判断
while (index < expression.Length && expression[index] >= && expression[index] <= )
{ str += expression[index]; index++;
} list.Add(str);
} } while (index < expression.Length); return list;
}
    /// <summary>
/// 中缀转后缀
/// </summary>
/// <param name="expression"></param>
/// <returns></returns>
public static List<string> ParseSuffixExpression(List<string> expression)
{
//存储中间结果
List<string> list = new List<string>();
//符号栈
Stack<string> stack = new Stack<string>(); foreach (var item in expression)
{
//多位数判断 如果是数字直接加入list
if (Regex.IsMatch(item, "\\d+"))
{
list.Add(item);
}
//如果是左括号,直接入符号栈
else if (item.Equals("("))
{
stack.Push(item);
}
//如果是右括号
else if (item.Equals(")"))
{
//依次弹出stack栈顶的运算符,并存入list,直到遇到左括号为止
while (!stack.Peek().Equals("("))
{
list.Add(stack.Pop());
}
//将(也出栈
stack.Pop();
}
//如果是*/+-
else
{
//循环判断item的优先级小于或者等于stack栈顶运算符,将stack栈顶的运算符出栈并加入到list中
while (stack.Count != && Operation.GetValue(stack.Peek()) >= Operation.GetValue(item))
{
list.Add(stack.Pop());
}
//将item入栈
stack.Push(item);
}
} //将stack剩余的运算符依次入list
while (stack.Count!=)
{
list.Add(stack.Pop());
} return list;
}
    public class Operation
{
private static int ADD = ;
private static int SUB = ;
private static int MUL = ;
private static int DIV = ; public static int GetValue(string operation)
{
int result = ; switch (operation)
{
case "+":
result = ADD;
break;
case "-":
result = SUB;
break;
case "*":
result = MUL;
break;
case "/":
result = DIV;
break;
default:
// Console.WriteLine("不存在该运算符");
break;
} return result;
}
}
        /// <summary>
/// 计算
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public static int Calculate(List<string> list)
{
//创建栈
Stack<string> stack = new Stack<string>(); //循环遍历
list.ForEach(item =>
{
//正则表达式判断是否是数字,匹配的是多位数
if (Regex.IsMatch(item,"\\d+"))
{
//如果是数字直接入栈
stack.Push(item);
}
//如果是操作符
else
{
//出栈两个数字,并运算,再入栈
int num1 =int.Parse(stack.Pop()); int num2 = int.Parse(stack.Pop()); int result = ; if(item.Equals("+"))
{
result = num2 + num1;
}
else if(item.Equals("*"))
{
result = num2 * num1;
}
else if(item.Equals("/"))
{
result = num2 / num1;
}
else if (item.Equals("-"))
{
result = num2 - num1;
}
else
{
throw new Exception("无法识别符号");
} stack.Push(""+result);
}
}); //最后把stack中数据返回
return int.Parse(stack.Pop());
}
    public class ReversePolandTransformation
{ public static void Test()
{
string expression = "1+((2+3)*4)-5"; //将字符串转换成List
List<string> infixExpression = ToInfixExpression(expression); string str = ""; infixExpression.ForEach(item =>
{
str = str + item + ",";
}); Console.WriteLine("中缀表达式对应的List:"+str); str = ""; //将中缀表达式转换成后缀表达式
List<string> suffixExpression = ParseSuffixExpression(infixExpression); suffixExpression.ForEach(item =>
{
str = str + item + ",";
}); Console.WriteLine("\n后缀表达式对应的List:"+str); //结果计算
int result =PolandNotation.Calculate(suffixExpression); Console.WriteLine($"\n{expression}={result}");
}
}

C#数据结构与算法系列(十):中缀表达式转后缀表达式的更多相关文章

  1. C#数据结构与算法系列(十):逆波兰计算器——逆波兰表达式(后缀表达式)

    1.介绍 后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后 2.举例说明 (3+4)*5-6对应的后缀表达式就是3 4 +5 * 6 - 3.示例 输入一个逆波兰表达式(后缀表达 ...

  2. C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611

    09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...

  3. javascript实现数据结构与算法系列:栈 -- 顺序存储表示和链式表示及示例

    栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.表尾为栈顶(top),表头为栈底(bottom),不含元素的空表为空栈. 栈又称为后进先出(last in first out)的线性表. 堆 ...

  4. 利用stack结构,将中缀表达式转换为后缀表达式并求值的算法实现

    #!/usr/bin/env python # -*- coding: utf-8 -*- # learn <<Problem Solving with Algorithms and Da ...

  5. 数据结构(3) 第三天 栈的应用:就近匹配/中缀表达式转后缀表达式 、树/二叉树的概念、二叉树的递归与非递归遍历(DLR LDR LRD)、递归求叶子节点数目/二叉树高度/二叉树拷贝和释放

    01 上节课回顾 受限的线性表 栈和队列的链式存储其实就是链表 但是不能任意操作 所以叫受限的线性表 02 栈的应用_就近匹配 案例1就近匹配: #include <stdio.h> in ...

  6. 数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解

    数据结构与算法系列2 线性表 使用java实现动态数组+ArrayList源码详解 对数组有不了解的可以先看看我的另一篇文章,那篇文章对数组有很多详细的解析,而本篇文章则着重讲动态数组,另一篇文章链接 ...

  7. 数据结构与算法系列2 线性表 链表的分类+使用java实现链表+链表源码详解

    数据结构与算法系列2.2 线性表 什么是链表? 链表是一种物理存储单元上非连续,非顺序的存储结构,数据元素的逻辑顺序是通过链表的链接次序实现的一系列节点组成,节点可以在运行时动态生成,每个节点包括两个 ...

  8. Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算

    中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...

  9. C#数据结构与算法系列(八):栈(Stack)

    1.介绍 栈是一个先入后出(FILO-First In Last Out)的有序列表 栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的特殊线性表.允许插入和删除的一端,为变化的一端,称为栈顶 ...

  10. 数据结构Java实现06----中缀表达式转换为后缀表达式

    本文主要内容: 表达式的三种形式 中缀表达式与后缀表达式转换算法 一.表达式的三种形式: 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3.我们从小做数学题时,一直使用的就是中缀表达式. 后 ...

随机推荐

  1. 【Ubuntu】快捷键

    版本:Ubuntu18.04 1. 终端(terminal ) alt + ctrl + t # 打开终端 shift + shift + t # 新建终端标签页 ctrl + c # 强制停止程序运 ...

  2. [Unity2d系列教程] 002.引用外部DLL - C

    上一篇我们学习了Unity调用C#生成的外部DLL,但是有时候我们需要访问底层,不能不适用C生成的DLL.下面就让我们一起学习下,C如何生成. 1.创建一个C的控制台程序 2.点击确定->点击下 ...

  3. Xilinx ISE多功能移位寄存器仿真及Basys2实验板实验

    移位寄存器实现Verilog代码: `timescale 1ns / 1ps module add( input clk, input reset, input [1:0] s, input dl, ...

  4. vnc远程工具的使用,Windows系统下VNC远程工具的使用教程

    服务器管理工具可以作为VNC的客户端进行VNC的相关操作,是一款功能强大的VNC客户端软件!同时,它也可以作为FTP的客户端,来进行FTP的相关操作!它能够连接Windows和Linux系统下的服务器 ...

  5. SpringCloud Netflix (六):Config 配置中心

    ------------恢复内容开始------------ SpringCloud Config 配置中心 Config 配置中心 Spring Cloud Config为分布式系统中的外部化配置提 ...

  6. Java分层经验

    在学习和使用Java的过程中,我们时常要用到各种工具与技术,它们在某些时候可以大幅度地简化编程,利用好它们,可以让代码更强壮.下面的表格是我总结的关于java开发可能会用到的工具与它们在项目中扮演的角 ...

  7. Java实现 洛谷 采药

    题目描述 辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处都是草药的山洞里对他说:" ...

  8. Java实现 LeetCode 88 合并两个有序数组

    88. 合并两个有序数组 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组. 说明: 初始化 nums1 和 nums2 的元 ...

  9. java中Timer类的详细介绍(详解)

    一.概念 定时计划任务功能在Java中主要使用的就是Timer对象,它在内部使用多线程的方式进行处理,所以它和多线程技术还是有非常大的关联的.在JDK中Timer类主要负责计划任务的功能,也就是在指定 ...

  10. Java实现信用卡校验

    当你输入信用卡号码的时候,有没有担心输错了而造成损失呢?其实可以不必这么担心,因为并不是一个随便的信用卡号码都是合法的,它必须通过Luhn算法来验证通过. 该校验的过程: 1.从卡号最后一位数字开始, ...