第八周(11.04-11.10)----结对项目----逆波兰
基本概念
逆波兰式(ReversePolishnotation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)。
中序表达式就是我们数学中常见的算式形式。
举例说明
中序表达式:3+4*5-6
转化成逆波兰式:3 4 5 * + 6 -
算法思想
首先建立两个栈,一个数据栈OPDN,一个操作符栈OPTR。
先将“#”栈底标志放到操作符栈。
从中序表达式pre的第一个字符读起:
1.如果pre[i]是操作数,就直接入数据栈;
2.如果pre[i]为左括号,就压入操作符栈;
3.如果pre[i]为右括号,就将操作符栈中的运算符一次出栈并依次压入数据栈,一直到操作符栈顶元素为左括号停止,但是这个时候要将左括号出栈,而且不压入数据栈;
4.如果pre[i]为操作符:
a.如果操作符栈为空,就将操作符pre[i]压入数据栈;
b.如果pre[i]的优先级大于操作符栈顶元素的优先级,就将此pre[i]压入数据栈;
c.如果操作符栈不为空而且pre[i]的优先级小于等于操作符栈顶元素的优先级,就将操作符栈中的元素依次出栈并且压入数据栈,指导不满足上述条件,将此操作符pre[i]压入数据栈。
5.如果遍历完整个中序的表达式,操作符栈还存有运算符,就将全部运算符出栈并且压入数据栈,直到为空。
6.最后将整个数据栈的元素依次压入操作符栈,然后正序输出操作符栈就可以得到逆波兰式了。
利用栈将中序表达式转换成逆波兰式代码表达
建立computer类和Mycounter主类
class computer
类方法 | 说明 |
public int randomnum() | 返回一个随机数 |
public String symbol() | 返回+-*/中的一个随机符号 |
public boolean isNum(String pre) | 判断中序表达式中的字符是否为数字 |
public boolean isoperator(String sym) | 判断中序表达式中的字符是否为“+,-,*,/”符号中的一种 |
public int priority(String sym) | 返回每种符号的优先级表示数 |
void toback(String pre[]) | 将输入的pre[]转换成逆波兰式后输出 |
1 package Mycounter; 2 import java.lang.Math; 3 import java.util.Stack; 4 import java.util.regex.Matcher; 5 import java.util.regex.Pattern; 6 public class computer { 7 //生成0-100的随机数 8 public int randomnum() { 9 int random = (int)(Math.random()*10);//Math.random的范围是[0.0-1.0] 10 return random; 11 12 } 13 //生成一个随机符号 14 public String symbol(){ 15 16 int i=0; 17 switch(i=(int) (Math.random() * 4)) 18 { 19 case 0: 20 return "+"; 21 case 1: 22 return "-"; 23 case 2: 24 return "*"; 25 case 3: 26 return "/"; 27 default : 28 return null; 29 } 30 31 } 32 //判断是否为数字 33 public boolean isNum(String pre){ 34 Pattern pattern = Pattern.compile("[0-9]*"); //通过正则表达式判断String类型是否为数字 35 Matcher isNum = pattern.matcher(pre); 36 if( !isNum.matches() ){ 37 return false; 38 } 39 return true; 40 } 41 //判断时否为符号 42 public boolean isoperator(String sym){ 43 switch(sym) 44 { 45 case "+": 46 return true; 47 case "-": 48 return true; 49 case "*": 50 return true; 51 case "/": 52 return true; 53 default : 54 return false; 55 } 56 } 57 //判断符号优先级,#为栈底标志 58 public int priority(String sym){ 59 switch(sym) 60 { 61 case "#": 62 return -1; 63 case "(": 64 return 0; 65 case "+": 66 return 1; 67 case "-": 68 return 1; 69 case "*": 70 return 2; 71 case "/": 72 return 2; 73 default : 74 return -1; 75 } 76 } 77 //中缀表达式转化前缀表达式 78 void toback(String pre[]){ 79 80 String bottom="#"; 81 Stack<String> OPTR = new Stack(); //运算符栈 82 Stack<String> OPND = new Stack(); //数据栈 83 84 OPTR.push(bottom); // 首先把结束标志‘#’放入栈底 85 86 for(int k=0;k<pre.length;k++) 87 { 88 if(isNum(pre[k])) // 遇到数直接写入后缀表达式 89 { 90 OPND.push(pre[k]); 91 } 92 else if (pre[k]=="(") // 遇到“(”不用比较直接入栈 93 OPTR.push(pre[k]); 94 else if(pre[k] ==")") // 遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式 95 { 96 while(OPTR.peek()!="(") 97 { 98 OPND.push( OPTR.peek()); 99 OPTR.pop(); 100 } 101 OPTR.pop(); // 将“(”出栈,后缀表达式中不含小括号 102 } 103 else if (isoperator(pre[k])) 104 { 105 while(!OPTR.empty() && priority(pre[k]) <= priority(OPTR.peek())) 106 { 107 // 当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程 108 OPND.push(OPTR.peek()); 109 OPTR.pop(); 110 } 111 OPTR.push(pre[k]);// 当前操作符栈为空或者当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈 112 } 113 114 } 115 while(OPTR.peek() != "#") // 将所有的操作符加入后缀表达式 116 { 117 OPND.push(OPTR.peek()); 118 OPTR.pop(); 119 } 120 OPTR.pop(); 121 122 //利用操作符栈逆序即可得到后缀表达式 123 while(!OPND.empty()) 124 { 125 OPTR.push(OPND.peek()); 126 OPND.pop(); 127 } 128 while(!OPTR.empty()) 129 { 130 System.out.print(OPTR.peek()+" "); 131 OPTR.pop(); 132 } 133 134 } 135 }
Mycounter
主类控制
1 package Mycounter; 2 3 import java.util.Scanner; 4 5 import Mycounter.computer; 6 public class Mycounter { 7 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 computer yl = new computer(); 11 int y1=yl.randomnum();//随机数y1,y2,y3,y4 12 int y2=yl.randomnum(); 13 int y3=yl.randomnum(); 14 int y4=yl.randomnum(); 15 String sym1=yl.symbol();//随机操作符sym1,sym2,sym3 16 String sym2=yl.symbol(); 17 String sym3=yl.symbol(); 18 19 String[] zhongshi={String.valueOf(y1),sym1,String.valueOf(y2),sym2,String.valueOf(y3),sym3,String.valueOf(y4)} ;//按中序表达式顺序存入String[] 20 for(int i=0;i<zhongshi.length;i++){ //输出中序表达式 21 System.out.print(zhongshi[i]); 22 23 } 24 System.out.println(""); 25 yl.toback(zhongshi); //转换成逆波兰式 26 } 27 28 }
鸣谢
感谢http://blog.csdn.net/axiqia/article/details/50538878#逆波兰表达式中序表达式转后序表式式 博主的写出这么详尽的算法解读和代码演示
代码
https:https://git.coding.net/YangXiaomoo/fourcount.git
ssh:git@git.coding.net:YangXiaomoo/fourcount.git
git:git://git.coding.net/YangXiaomoo/fourcount.git