逆波兰表达式实验

原创

转载请注明出处!

包含文件:

1.MainFace.java

2.JiSuan.java

3.HzExp.java

实现功能:中缀表达式转换成后缀表达式,利用后缀表达式进行计算.

界面如图:

逆波兰表达式实验

逆波兰表达式的产生及计算实验设计思想及算法

u逆波兰式定义

将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表达式也称做后缀式。逆波兰式的特点在于运算对象顺序不变,运算符号位置反映运算顺序。

u产生逆波兰式的前提

中缀算术表达式

u逆波兰式生成的设计思想及算法

(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。

(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”

(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。

(4)如果不是数字,该字符则是运算符,此时需比较优先关系。

做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。

(5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

产生后缀表达式核心代码:

public boolean buoLan(){ /*核心代码,主方法*/ int k=0; while(k<str.length()){ subStr=str.substring(k+1); ch=str.charAt(k); if((int)ch>=48 && (int)ch<=57 || ((int)ch>=65 && (int)ch<=90) || ((int)ch>=97 && (int)ch<=122)){ s=getStr(str.substring(k)); k=k+s.length(); results.append(s); String[] values={String.valueOf(++n),String.valueOf(ch),subStr,String.valueOf(fuHaoZhan),results.toString()}; tableModel.addRow(values); continue; }else{ if(ch=='('){ fuHaoZhan.add(ch); k++; }else if(ch==')'){ if(fuHaoZhan.size()==0){ return false; } if(fuHaoZhan.get(fuHaoZhan.size()-1)!='('){ results.append(fuHaoZhan.get(fuHaoZhan.size()-1)); fuHaoZhan.remove(fuHaoZhan.size()-1); }else{ k++; fuHaoZhan.remove(fuHaoZhan.size()-1); } }else{ if(fuHaoZhan.size()==0){ if(ch=='-' && k==0)ch='@'; fuHaoZhan.add(ch); k++; }else{ if(ch=='-'){ if(((int)str.charAt(k-1)<48 || ((int)str.charAt(k-1)>57 && (int)str.charAt(k-1)<65) || ((int)str.charAt(k-1)>90) && ((int)str.charAt(k-1)<97) || ((int)str.charAt(k-1)>122) )&& str.charAt(k-1)!=')'){ ch='@'; } } if(fuHaoZhan.get(fuHaoZhan.size()-1)=='('){ fuHaoZhan.add(ch); k++; }else{ for(int j=0;j<fuHao.length;j++){ if(fuHao[j]==ch)x=j; if(fuHao[j]==fuHaoZhan.get(fuHaoZhan.size()-1))y=j; } if(x-y>=2){ fuHaoZhan.add(ch); k++; }else{ results.append(fuHaoZhan.get(fuHaoZhan.size()-1)); fuHaoZhan.remove(fuHaoZhan.size()-1); } } } } } String[] values={String.valueOf(++n),String.valueOf(ch),subStr,String.valueOf(fuHaoZhan),results.toString()}; tableModel.addRow(values); } return true; }

计算后缀表达式核心代码:

public double compute(){ /*根据后缀表达式计算--核心代码!*/ switch(ch[--i]) { //递归的思想,需要好好理解。。。 case '+': return compute() + compute(); case '-': return - compute() + compute(); case '*': return compute() * compute(); case '/': return 1/compute() * compute(); default : { System.out.println(atof(ch[i])); return atof(ch[i]); //将字符串转化成浮点数 } } }

代码文件:MainFace.java

package BoLan; /* * @作者: huali_xuqu/Versers; * @转载请注明出处! * @2011.3.2; * @MainFace.java; * */ import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.table.DefaultTableModel; public class MainFace extends JFrame implements ActionListener{ private static final long serialVersionUID = -4801487427948417304L; JTextField inStr; JTextField outStr; JTextField result; JButton boLan; JButton compute; JLabel jl1; JLabel jl2; JLabel jl3; JTable assignment; JTable table; DefaultTableModel tableModel1; DefaultTableModel tableModel; JScrollPane scrollPane; JScrollPane scrollPane1; /*以上为组件声明*/ MainFace(){/*构造函数,初始化组件*/ setTitle("逆波兰表达式实验"); setSize(400,350); setLocation(350,200); setLayout(null); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); init(); } public void init(){ inStr=new JTextField(); inStr.setBounds(5,5,300,20); this.add(inStr); /***/ outStr=new JTextField(); outStr.setBounds(5,185,375,20); outStr.setEditable(false); this.add(outStr); /***/ result=new JTextField(); result.setBounds(230,230,80,20); result.setEditable(false); this.add(result); /***/ boLan=new JButton("推导"); boLan.setBounds(305,4,75,21); boLan.addActionListener(this); this.add(boLan); /***/ compute=new JButton("计算"); compute.setBounds(100,205,75,20); compute.addActionListener(this); this.add(compute); /***/ jl1=new JLabel("请先赋值"); jl1.setBounds(20,210,80,80); this.add(jl1); /***/ jl2=new JLabel("结果"); jl2.setBounds(195,200,75,80); this.add(jl2); /***/ jl3=new JLabel("赋值完后请先双击“双击”后再计算"); jl3.setBounds(175,260,210,20); this.add(jl3); /***/ String[] columnNames1={"变量"}; tableModel1=new DefaultTableModel(null,columnNames1); assignment= new JTable(tableModel1); scrollPane1=new JScrollPane(assignment); scrollPane1.setBounds(100,222,75,85); this.add(scrollPane1); /***/ String[] columnNames={"步骤","当前符号","输入区","运算符号栈","输出区"}; tableModel = new DefaultTableModel(null,columnNames); table=new JTable(tableModel); scrollPane=new JScrollPane(table); scrollPane.setBounds(5,30,375,150); this.add(scrollPane); } public void actionPerformed(ActionEvent e) { if(e.getSource()==boLan){ /*推导按钮事件监听*/ if(inStr.getText().equals("")) /*过滤输入为空的情况*/ JOptionPane.showMessageDialog(this, "输入不能为空"); else{ int m=tableModel.getRowCount(); for(int i=0;i<m;i++){ tableModel.removeRow(0); } int n=tableModel1.getRowCount(); for(int i=0;i<n;i++){ tableModel1.removeRow(0); } HzExp he=new HzExp(inStr.getText(),tableModel); /*调用HzExp类求后缀表达式*/ he.buoLan(); outStr.setText(he.getResults()); new JiSuan(outStr.getText(),tableModel1).searchVar(); } } if(e.getSource()==compute){ /*计算按钮事件监听*/ if(outStr.getText().equals("")) /*过滤输出为空的情况*/ JOptionPane.showMessageDialog(this, "输出栏为空"); else result.setText(String.valueOf((new JiSuan(outStr.getText(),tableModel1).compute()))); /*调用JiSuan类的compute方法计算结果*/ } } public static void main(String[] args){ new MainFace(); } }

代码文件:JiSuan.java

package BoLan; /* * @作者: huali_xuqu/Versers; * @转载请注明出处! * @2011.3.2; * JiSuan.java; * 此类用于基于后缀表达式的变量赋值计算; * */ import javax.swing.table.DefaultTableModel; public class JiSuan { String str; String st; StringBuilder stri; DefaultTableModel ass; int i,k; char[] ch; String[] c={"","","","","","","","","",""}; JiSuan(String str,DefaultTableModel ass){ this.str=str; this.ass=ass; stri=new StringBuilder(); stri.append(str); k=0; for(int j=0;j<stri.length();j++){ /*过滤带有@的字符串即含负数的后缀表达式*/ if(stri.charAt(j)=='@'){ stri.insert(j-1, '0'); j++; } } str=stri.toString(); str=str.replace('@','-'); ch=str.toCharArray(); i=ch.length; } public double compute(){ /*根据后缀表达式计算--核心代码!*/ switch(ch[--i]) { //递归的思想,需要好好理解。。。 case '+': return compute() + compute(); case '-': return - compute() + compute(); case '*': return compute() * compute(); case '/': return 1/compute() * compute(); default : return atof(ch[i]); //将字符串转化成浮点数 } } public void searchVar(){ /*检索逆波兰式变量名以及变量数。*/ for(int i=0;i<ch.length;i++){ boolean isTrue=true; if(!(((int)ch[i]>=65 && (int)ch[i]<=90) || ((int)ch[i]>=97 && (int)ch[i]<=122))) continue; for(int n=0;n<c.length;n++){ if(c[n].equals(String.valueOf(ch[i]))){ isTrue=false; break; } } if(isTrue==false)continue; c[k++]=String.valueOf(ch[i]); String[] values={c[k-1]+": "}; ass.addRow(values); } ass.addRow(new String[]{"双击"}); } public double atof(char cha){/*返回该字符所表示的变量的值*/ double d=cha-48; st=new String(); for(int i=0;i<ass.getRowCount()-1;i++){ st=ass.getValueAt(i,0).toString(); if(st.charAt(0)==cha){ d=Double.valueOf(st.substring(2)); break; } } return d; } }

代码文件:HzExp.java

package BoLan; /* * @作者: huali_xuqu/Versers; * @转载请注明出处! * @2011.3.2; * HzExp.java; * */ import java.util.ArrayList; import javax.swing.table.DefaultTableModel; public class HzExp { DefaultTableModel tableModel; String str; /*存放输入的中缀表达式(尾部必须加“#”号)*/ String subStr; /*存放每步剥剪后剩下的子中缀表达式*/ String s; /*存放变量(有些变量不止是单字符)*/ char ch; /*被剥离的字符*/ char[] fuHao; /*内部符号优先级表*/ int x,y,n; ArrayList<Character> fuHaoZhan; /*符号栈(动态char数组)*/ StringBuilder results; /*返回的后缀表达式既结果*/ public HzExp(String str,DefaultTableModel tableModel){ /*构造函数*/ this.str=str; this.tableModel=tableModel; n=0; //System.out.println("Enter"); if(str.charAt(str.length()-1)!='#')return ;/*表达式末尾不为“#”,返回错误标志待改*/ results=new StringBuilder(); fuHaoZhan=new ArrayList<Character>(); init(); } public boolean buoLan(){ /*核心代码,主方法*/ int k=0; while(k<str.length()){ subStr=str.substring(k+1); ch=str.charAt(k); if((int)ch>=48 && (int)ch<=57 || ((int)ch>=65 && (int)ch<=90) || ((int)ch>=97 && (int)ch<=122)){ s=getStr(str.substring(k)); k=k+s.length(); results.append(s); String[] values={String.valueOf(++n),String.valueOf(ch),subStr,String.valueOf(fuHaoZhan),results.toString()}; tableModel.addRow(values); continue; }else{ if(ch=='('){ fuHaoZhan.add(ch); k++; }else if(ch==')'){ if(fuHaoZhan.size()==0){ return false; } if(fuHaoZhan.get(fuHaoZhan.size()-1)!='('){ results.append(fuHaoZhan.get(fuHaoZhan.size()-1)); fuHaoZhan.remove(fuHaoZhan.size()-1); }else{ k++; fuHaoZhan.remove(fuHaoZhan.size()-1); } }else{ if(fuHaoZhan.size()==0){ if(ch=='-' && k==0)ch='@'; fuHaoZhan.add(ch); k++; }else{ if(ch=='-'){ if(((int)str.charAt(k-1)<48 || ((int)str.charAt(k-1)>57 && (int)str.charAt(k-1)<65) || ((int)str.charAt(k-1)>90) && ((int)str.charAt(k-1)<97) || ((int)str.charAt(k-1)>122) )&& str.charAt(k-1)!=')'){ ch='@'; } } if(fuHaoZhan.get(fuHaoZhan.size()-1)=='('){ fuHaoZhan.add(ch); k++; }else{ for(int j=0;j<fuHao.length;j++){ if(fuHao[j]==ch)x=j; if(fuHao[j]==fuHaoZhan.get(fuHaoZhan.size()-1))y=j; } if(x-y>=2){ fuHaoZhan.add(ch); k++; }else{ results.append(fuHaoZhan.get(fuHaoZhan.size()-1)); fuHaoZhan.remove(fuHaoZhan.size()-1); } } } } } String[] values={String.valueOf(++n),String.valueOf(ch),subStr,String.valueOf(fuHaoZhan),results.toString()}; tableModel.addRow(values); } return true; } public void init(){ /*相差2显示优先级高地,如果相差1表示优先级一致*/ fuHao=new char[9]; fuHao[0]='#'; fuHao[1]='$'; fuHao[2]='-'; fuHao[3]='+'; fuHao[4]='$'; fuHao[5]='*'; fuHao[6]='/'; fuHao[7]='$'; fuHao[8]='@'; } public String getStr(String str){ /*返回变量*/ String st=str; boolean isNull=true;//全部是字符串 char cha; for(int i=0;i<str.length();i++) { cha=str.charAt(i); if(cha=='('){ st=str.substring(0,i); break; } if(cha==')'){ st=str.substring(0,i); break; } for(int j=0;j<fuHao.length;j++){ if(fuHao[j]==cha){ st=str.substring(0,i); isNull=false; break; } } if(isNull==false)break; st=str; } return st; } public String getResults(){ return results.toString(); } }

看了点评下哦~给点建议啥的,谢啦~