前缀表达式、中缀表达式、后缀表达式

中缀表达式就是我们日常看到的数学表达式:比如(2+4)*2,对于人类来说很直观,但是对于计算机而言,这种表达式很不容易理解。于是就有了前缀表达式和后缀表达式。

前缀表达式

前缀表达式是指将操作符放在前面,然后再放置操作数,比如对前面表达式而言,前缀表达式为*、+、2、4、2;

后缀表达式

后缀表达式是指将先放操作数,然后再放操作符,比如对签名表达式而言,后缀表达式为2、4、+、2、*

可以总结出规律,前缀表达式和后缀表达式的操作符顺序是相反的,而操作数的顺序是相同的。

为什么计算机对后缀表达式(前缀)比较方便

我们看到前缀表达式中不存在诸如括号改变优先级的符号,事实上,通过前缀表达式和后缀表达式可以很容易构造一颗运算树,通过该运算树,可以使用递归的方式很方便计算表达式,比如该运算式构成的树为:

这里写图片描述
然后这里,只需要int leftVal = calculate(root.left);int rightVal = calculate(root.right);然后可以计算出root值。

前缀表达式转树

前缀表达式如何变成一颗运算树呢?
通过前缀表达式,从后向前遍历,当出现运算数时,将运算数变成Node对象压栈,当出现运算符时,弹出栈中前两个对象,然后再构成一颗子树,入栈。。看代码吧

package com.dacas.converter;

import java.util.Stack;

/**
 * Created by dave on 2016/4/6.
 */
public class ConvertPrefixExpressionToTree implements IConverter {
    @Override
    public TreeNode convert(String expression) {
        char[] chars = expression.toCharArray();
        Stack<TreeNode> nodes = new Stack<>();

        for(int i = chars.length-1;i>=0;i--){
            TreeNode root = new TreeNode(chars[i]);
            if(!isValid(chars[i])){
                TreeNode top1 = nodes.pop();
                TreeNode top2 = nodes.pop();

                root.setLeftNode(top1);
                root.setRightNode(top2);
            }
            nodes.push(root);
        }
        return nodes.size() == 1?nodes.pop():null;
    }
}

后缀表达式转树

后缀表达式和前缀表达式构造树的方式非常类似。只是这次从前向后遍历。具体看代码

package com.dacas.converter; /**
 * Created by dave on 2016/4/6.
 */
import java.util.Stack;
/**
 * 将后缀表达式转换成一个表达式树
 */
public class ConvertPostExpressionToTree implements IConverter{
    @Override
    public TreeNode convert(String expression) {
        Stack<TreeNode> nodes = new Stack<>();
        char[] chars = expression.toCharArray();

        for(char ch:chars){
            TreeNode root = new TreeNode(ch);
            if(!isValid(ch)) {
                TreeNode top1 = nodes.pop();
                TreeNode top2 = nodes.pop();

                root.setLeftNode(top2);
                root.setRightNode(top1);
            }
            nodes.push(root);
        }
        return nodes.size() == 1?nodes.pop():null;
    }
}

中缀表达式转后缀表达式

  1. 使用两个栈,一个是操作符栈,一个是操作数栈;
  2. 遍历中缀表达式,当一个字符为操作数时,压入操作数栈;当为操作码时,如果操作码栈为空,直接压入,如果为(,直接压入操作码栈,如果字符为),则出栈到(位置处,当操作码栈不为空时,比较栈顶元素与当前元素的优先级,如果当前元素优先级小于等于栈顶元素,则出栈,否则入栈。
package com.dacas.converter;

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

/**
 * Created by dave on 2016/4/6.
 * 将中缀表达式转换成后缀表达式
 */
public class ConvertMiddleExpressionToPostExpression{
    static Map<Character,Integer> maps = new HashMap<>();
    static {
        maps.put('(',0);
        maps.put('+',1);
        maps.put('-',1);
        maps.put('*',2);
        maps.put('/',2);
    }
    public String convert(String midExpression){
        Stack<Character> operators = new Stack<>();//操作符
        Stack<String> operands = new Stack<>();//操作数

        char[] chars = midExpression.toCharArray();
        for(char ch:chars){
            if(ch>='0' && ch<='9'){
                operands.push(ch+"");
            }else if(ch == '(') {
                operators.push(ch);
            }else if(ch == ')'){
                char top;
                while((top = operators.pop())!='('){
                    String ch1 = operands.pop();
                    String ch2 = operands.pop();
                    operands.push(ch2 + "," + ch1 + "," + top);
                }
            }else{//操作符
                while (!operators.isEmpty() && comparePriority(operators.peek(), ch)) {//top >= ch,pop out
                    String ch1 = operands.pop();
                    String ch2 = operands.pop();
                    operands.push(ch2 + "," + ch1 + "," + operators.pop());
                }
                operators.push(ch);
            }
        }
        while(!operators.isEmpty()){
            String ch1 = operands.pop();
            String ch2 = operands.pop();
            operands.push(ch2+","+ch1+","+operators.pop());
        }
        return operands.pop();
    }
    private boolean comparePriority(char ch1,char ch2){
        int int1 = maps.get(ch1);
        int int2 = maps.get(ch2);
        return int1 >= int2;
    }
}
Main.java

import com.dacas.converter.*;


/**
 * Created by dave on 2016/4/6.
 */
//数据结构与算法分析第4章
public class Main {
    public static void main(String[] args) {
        performConvertPostExpressionToTree();
    }
    private static void performConvertPostExpressionToTree(){
        /***********后缀表达式转树***********/
        String postfix = "ab+cde+**";
        IConverter postConverter = new ConvertPostExpressionToTree();
        TreeNode postNode = postConverter.convert(postfix);
        System.out.println(postNode);
        /************前缀表达式转树*****************/
        String prefix = "-*+3456";
        IConverter preConverter = new ConvertPrefixExpressionToTree();
        TreeNode preNode = preConverter.convert(prefix);
        System.out.println(preNode);
        /****************中缀表达式转后缀表达式**********************/
        String midfix = "3*(4+5/2-2*3/8)/2";
        ConvertMiddleExpressionToPostExpression midConverter = new ConvertMiddleExpressionToPostExpression();
        String postfixExpression = midConverter.convert(midfix);
        System.out.println(postfixExpression);

        String[] strs = postfixExpression.split(",");
        String newString = "";
        for(String tmp:strs){
            newString+=tmp+"";
        }
        TreeNode postNode2 = postConverter.convert(newString);
        System.out.println(postNode2);
    }
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值