1、本章内容主要参考于《Java数据结构和算法第二版》这本书。平时说的算术表达式就是中缀表达式,对计算机的算法来说如果要直接求算术表达式的值是比较困难的,所以可以按下面两步来实现算法会更容易:
2、中缀表达式转后缀表达式逻辑图
3、中缀表达式转后缀表达式代码实现
package stack;
/**
* 中缀表达式转换成后缀表达式
*/
public class InToPost {
private StackE stack;
private String input;//输入中缀表达式
private String output = "";//输出后缀表达式
//加减(+-)的优先权
private static final int PRECEDENCE_1 = 1;
//乘除(*/)的优先权
private static final int PRECEDENCE_2 = 2;
public InToPost(String in){
input = in;
int stackSize = input.length();
stack = new StackE(stackSize);
}
//中缀表达式转换成后缀表达式
public String doTrans(){
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);//中缀表达式中的字符
stack.displayStack("For " + ch + " ");
switch (ch) {
case '+':
case '-':
getOper(ch, PRECEDENCE_1);//判断加减(+-)号是入栈,还是直接添加到字符串output中
break;
case '*':
case '/':
getOper(ch, PRECEDENCE_2);//判断乘除(*/)号是入栈,还是直接添加到字符串output中
break;
case '(':
stack.push(ch+"");//遇到的字符是左括号'(',就直接压入栈顶
break;
case ')':
//将栈顶元素弹出栈并加入到字符串output中,直到弹出的元素是右括号')'为止,但是最后弹出的左括号不加入字符串output中
getParen(ch);
break;
default:
output += ch;
break;
}//end switch
}//end for
while (!stack.isEmpty()){
stack.displayStack("while ");
output += stack.pop();
}
stack.displayStack("End ");
return output;
}
/**
* 操作符opThis是加减乘除时,通过跟栈顶元素opTop对比优先权,如果opThis的优先权大于opTop,
* 那么直接将opThis压入栈顶,否则先将opTop弹出栈顶,然后再将opThis压入栈顶
* @param opThis 输入的操作符
* @param prec1 opThis的优先权,1代表加减;2代表乘除
*/
public void getOper(char opThis, int prec1){
while( !stack.isEmpty()){
char opTop = stack.pop().charAt(0);//弹出了栈顶元素,如果opThis的优先权大于opTop,那么需要重新压入opTop到栈顶
//如果栈顶元素是'(',那么重新压入刚弹出的栈顶元素'(',跳出循环并且将opThis直接压入栈顶
if (opTop == '('){
stack.push(opTop+"");
break;
}else{//如果栈顶元素是操作符,那么对比opThis跟opTop的优先权。
int prec2;//用来保存栈顶元素opTop的优先权
if (opTop == '+' || opTop == '-')
prec2 = 1;//如果栈顶元素为操作符'+'或者'-',那么优先权为1
else
prec2 = 2;//如果栈顶元素为操作符'*'或者'/',那么优先权为2
if (prec2 < prec1){//由于opThis的优先权大于opTop,所以opTop不需要弹出栈,因此需要重新把出栈的opTop重新压入栈顶
stack.push(opTop+"");//重新把出栈的opTop重新压入栈顶并且跳出循环,然后会把opThis压入栈顶
break;
}else{
output += opTop;//将操作符添加到输入字符串output中
}
}
}//end while
stack.push(opThis+"");//将opThis压入栈顶
}
/**
* 当输入字符opThis是右括号')'时,如果栈顶元素opTop不是左括号'(',就将栈顶元素opTop添加到字符串output中
* @param opThis
*/
public void getParen(char opThis){
while (!stack.isEmpty()){
char opTop = stack.pop().charAt(0);//弹出栈顶元素opTop
if (opThis == ')' && opTop == '(')//如果栈顶元素opTop是左括号'(',就退出循环
break;
else
output += opTop;//栈顶元素opTop不是左括号'(',将栈顶元素opTop添加到字符串output中
}
}
}
4、中缀表达式转后缀表达式测试
``
`package stack;
import java.io.IOException;
public class InfixApp {
public static void main(String[] args) throws IOException {
String input, output;
while(true){
System.out.print(“输入中缀表达式:”);
System.out.flush();
input = Util.getString();
if (input.equals(""))
break;
InToPost trans = new InToPost(input);
output = trans.doTrans();
System.out.println("后缀表达式: " + output);
}
}
}
5、计算后缀表达式的值。这个比较容易理解,看代码注释就可以。
package stack;
/**
* 后缀表达式求值
* |----------------------------------------------------------|
* |从后缀表达式中读取的元素 | 执行的动作 |
* |-----------------|----------------------------------------|
* | 操作数 | 入栈 |
* | 操作符 |从栈中提取两个操作数,用操作符将其执行运算。结果入栈 |
* |----------------------------------------------------------|
*/
public class ParsePost {
private StackE stack;
private String input;
public ParsePost(String s){
input = s;
}
/**
* 求解后缀表达式求值,目前只能求解个位数的值
* @return 返回计算结果
*/
public Integer doParse(){
stack = new StackE(20);//初始化一个大小为20的栈
char ch;
Integer num1, num2, tmpSum;
for (int i = 0; i < input.length(); i++) {
ch = input.charAt(i);//从后缀表达式中获取一个字符
stack.displayStack("" + ch + " ");//打印当前的字符
if (ch > '0' && ch <= '9'){
stack.push(Integer.parseInt(ch+""));//如果是数字就入栈
}else{//如果是操作符,就从栈顶开始,连续获取两个栈元素
num2 = stack.pop();//获取第一个栈元素
num1 = stack.pop();//获取第二个栈元素
switch (ch) {
case '+'://操作符ch为加,操作数num1和num2进行加法运行,运算结果保存到tmpSum中
tmpSum = num1 + num2;
break;
case '-':
tmpSum = num1 - num2;
break;
case '*':
tmpSum = num1 * num2;
break;
case '/':
tmpSum = num1 / num2;
break;
default:
tmpSum = 0;
break;
}//end switch
stack.push(tmpSum);//将结算结果tmpSum入栈
}//end else
}//end for
tmpSum = stack.pop();//后缀表达式中的元素读取完后,将计算结果出栈
return tmpSum;
}
}
`
6、
计算后缀表达式的值的测试代码及运行结果
package stack;
import java.io.IOException;
public class PostFixApp {
public static void main(String[] args) throws IOException {
String input;
Integer output;
while (true){
System.out.print(“输入后缀表达式: “);
System.out.flush();
input = Util.getString();//从键盘输入
if (input.equals(””))
break;
ParsePost parsePost = new ParsePost(input);
output = parsePost.doParse();//后缀表达式求值
System.out.println("解析后缀表达式后的值: " + output);
}
}
}
7、将中缀表达式转后缀表达式跟解析后缀表达式的值一起测试,即解析算术表达式的完整测试
package stack;
import java.io.IOException;
public class InfixToPostFixApp {
public static void main(String[] args) throws IOException {
String infixInput, infixOutput;
Integer postfixOutput;//保存解析的后缀表达式的值
while(true){
System.out.print("输入中缀表达式:");
System.out.flush();
infixInput = Util.getString();
if (infixInput.equals(""))
break;
InToPost trans = new InToPost(infixInput);//中缀表达式转换成后缀表达式
infixOutput = trans.doTrans();
System.out.println("后缀表达式: " + infixOutput);
ParsePost parsePost = new ParsePost(infixOutput);
postfixOutput = parsePost.doParse();//后缀表达式求值
System.out.println("解析后缀表达式的值: " + postfixOutput);
}
}
}
*/
public class StackE {
private int maxSize;//size of stack array
private Object[] stackArray;
private int top; //top of stack
//初始化栈,s是栈的大小
public StackE(int s){
maxSize = s;//set array size
stackArray = new Object[maxSize]; //create array
top = -1;// no items yet
}
//将item压入栈顶
public void push(E item) {// put item on top of stack
stackArray[++top] = item; //increment top, insert item
}
//将栈顶元素弹出并删除栈顶元素
public E pop() {//take item from top of stack
return (E) stackArray[top--];//access item, decrement top
}
//将栈顶元素弹出,不会删除栈顶元素
public E peek(){//peek at top of stack
return (E) stackArray[top];
}
//判断栈是否为空
public boolean isEmpty(){//true if stack is empty
return top == -1;
}
//判断栈是否满了
public boolean isFull(){//true if stack is full
return top == maxSize - 1;
}
//返回栈顶位置
public int getTop(){
return top;
}
//将栈中的第n个元素弹出,不会删除该元素
public E peekN(int n){//peek at top of stack
return (E) stackArray[n];
}
//获取栈的元素个数
public int size(){
return top+1;
}
public void displayStack(String s){
System.out.print(s);
System.out.print("Stack (bottom-->top): ");
for (int i = 0; i < size(); i++) {
System.out.print(peekN(i));
System.out.print(' ');
}
System.out.println();
}
}
package stack;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Util {
public static String getString() throws IOException{
InputStreamReader isr = new InputStreamReader(System.in);//从键盘输入
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
}
代码参考:https://github.com/gunder1129/android-tool/tree/master/JAVA%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%8F%8A%E7%AE%97%E6%B3%95
# 欢迎使用Markdown编辑器
你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。
## 新的改变
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
1. **全新的界面设计** ,将会带来全新的写作体验;
2. 在创作中心设置你喜爱的代码高亮样式,Markdown **将代码片显示选择的高亮样式** 进行展示;
3. 增加了 **图片拖拽** 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
4. 全新的 **KaTeX数学公式** 语法;
5. 增加了支持**甘特图的mermaid语法[^1]** 功能;
6. 增加了 **多屏幕编辑** Markdown文章功能;
7. 增加了 **焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置** 等功能,功能按钮位于编辑区域与预览区域中间;
8. 增加了 **检查列表** 功能。
[^1]: [mermaid语法说明](https://mermaidjs.github.io/)
## 功能快捷键
撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G
## 合理的创建标题,有助于目录的生成
直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用`TOC`语法后生成一个完美的目录。
## 如何改变文本的样式
*强调文本* _强调文本_
**加粗文本** __加粗文本__
==标记文本==
~~删除文本~~
> 引用文本
H~2~O is是液体。
2^10^ 运算结果是 1024.
## 插入链接与图片
链接: [link](https://www.csdn.net/).
图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw)
带尺寸的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw =30x30)
居中的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw#pic_center)
居中并且带尺寸的图片: ![Alt](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9hdmF0YXIuY3Nkbi5uZXQvNy83L0IvMV9yYWxmX2h4MTYzY29tLmpwZw#pic_center =30x30)
当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。
## 如何插入一段漂亮的代码片
去[博客设置](https://mp.csdn.net/console/configBlog)页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 `代码片`.
```javascript
// An highlighted block
var foo = 'bar';
一个简单的表格是这么创建的:
项目 | Value |
---|---|
电脑 | $1600 |
手机 | $12 |
导管 | $1 |
使用:---------:
居中
使用:----------
居左
使用----------:
居右
第一列 | 第二列 | 第三列 |
---|---|---|
第一列文本居中 | 第二列文本居右 | 第三列文本居左 |
SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:
TYPE | ASCII | HTML |
---|---|---|
Single backticks | 'Isn't this fun?' |
‘Isn’t this fun?’ |
Quotes | "Isn't this fun?" |
“Isn’t this fun?” |
Dashes | -- is en-dash, --- is em-dash |
– is en-dash, — is em-dash |
一个具有注脚的文本。1
Markdown将文本转换为 HTML。
您可以使用渲染LaTeX数学表达式 KaTeX:
Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n−1)!∀n∈N 是通过欧拉积分
Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=∫0∞tz−1e−tdt.
你可以找到更多关于的信息 LaTeX 数学表达式here.
可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:
这将产生一个流程图。:
我们依旧会支持flowchart的流程图:
如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
注脚的解释 ↩︎