1. 程式人生 > >字首表示式、中綴表示式、字尾表示式

字首表示式、中綴表示式、字尾表示式

中綴表示式就是我們日常看到的數學表示式:比如(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);
    }
}