簡體   English   中英

分流碼算法解析函數agruments

[英]Shunting-yard algorithm parsing function agruments

我試圖讓我的shunting-yard算法的實現工作。 它適用於數字和運算符。 但是當我嘗試向輸入添加函數時會出現問題。 因為函數參數在應該向右輸出時輸出到函數的左側。

測試程序

public class FrontTest
{
    public static void main(String[] args)
    {
        String str = "cbrt ( 8 )";
        System.out.println(ShuntTest.infixToPostfix(str));
    }
}

算法

import java.util.*;

public class ShuntTest
{
    public static String infixToPostfix(String infixStr)
    {
        Stack<String> operators = new Stack<String>();
        Queue<String> output = new LinkedList<String>();
        String[] tokens = infixStr.split("[\\s]");
        StringBuilder postfixStr = new StringBuilder();
        int tokensRemaining = tokens.length;

        final String PAREN_LEFT = "[\\(]";
        final String PAREN_RIGHT = "[\\)]";
        final String FUNCTION_ARGSEP = "[\\;]";

        for (int i = 0; i < tokens.length; i++)
        {
            if (isNumber(tokens[i]))
            {
                output.offer(tokens[i]);
            }
            else if (isFunction(tokens[i]))
            {
                operators.push(tokens[i]);
            }
            else if (tokens[i].matches(FUNCTION_ARGSEP))
            {
                while (!operators.empty() && operators.peek().matches(PAREN_RIGHT))
                {
                    output.offer(operators.pop());
                    if (operators.empty() && !operators.peek().matches(PAREN_RIGHT))
                    {
                        throw new RuntimeException("Mismatched Parentheses.");
                    }
                }
            }
            else if (isOperator(tokens[i]))
            {
                while (!operators.empty() && ((isOperator(operators.peek())
                        && ((isLeftAssociative(tokens[i]) == true && ((operatorPrecedence(tokens[i]) <= operatorPrecedence(operators.peek()))
                        || ((isLeftAssociative(tokens[i]) == false && ((operatorPrecedence(tokens[i]) < operatorPrecedence(operators.peek())))))))))))
                {
                    output.offer(operators.pop());
                }
                operators.push(tokens[i]);
            }
            else if (!operators.empty() && tokens[i].matches(PAREN_LEFT))
            {
                operators.push(tokens[i]);
            }
            else if (!operators.empty() && tokens[i].matches(PAREN_RIGHT))
            {
                while (!operators.empty() && !operators.peek().matches(PAREN_LEFT))
                {
                    output.offer(operators.pop());
                }
                if (!operators.empty())
                    {
                        operators.pop();
                    }
                else if (!operators.empty() && isFunction(operators.peek()))
                {
                    output.offer(operators.pop());
                }
                else if (operators.empty())
                {
                    throw new RuntimeException("Mismatched Parentheses.");
                }
            }
            tokensRemaining--;
        }

        if (tokensRemaining == 0)
        {
            while (!operators.empty())
            {
                if (operators.peek().matches(PAREN_LEFT)
                        || operators.peek().matches(PAREN_RIGHT))
                {
                    throw new RuntimeException("Mismatched Parentheses.");
                }
                output.offer(operators.pop());
            }
        }

        while (!output.isEmpty())
        {
            while (output.size() > 1)
            {
                postfixStr.append(output.poll() + " ");
            }
            postfixStr.append(output.poll());
        }
        return postfixStr.toString();
    }

    public static boolean isNumber(String str)
    {
        final String NUMBER = "^0?-?\\+?\\d+(\\.\\d+)?$";
        return str.matches(NUMBER) ? true : false;
    }

    public static boolean isOperator(String str)
    {
        switch (str)
        {
            case "^":   
            case "/":
            case "*":
            case "+":
            case "-":
                return true;
            default:
                return false;
        }
    }

    private static boolean isLeftAssociative(String str)
    {
        switch (str)
        {
            case "^":   
                return false;   
            case "/":
            case "*":
            case "+":
            case "-":
                return true;
            default:
                throw new IllegalArgumentException("Operator unknown: " + str);
        }   
    }

    private static int operatorPrecedence(String str)
    {
        switch (str)
        {
            case "^":
                return 4;
            case "/":
            case "*":
                return 3;
            case "+":
            case "-":
                return 2;
            default:
                throw new IllegalArgumentException("Operator unknown: " + str);
        }   
    }

    public static boolean isFunction(String str)
    {
        switch (str)
        {   
            case "sin": 
            case "cos":
            case "tan":
            case "sqrt":
            case "cbrt":
            case "root_of":
                return true;
            default:
                return false;
        }   
    }
}

例1:

輸入: cbrt ( 8 )

輸出: 8 cbrt

輸出應為: cbrt 8

例2:

輸入: cbrt ( 8 ) + sqrt ( 9 )

輸出: 8 9 sqrt + cbrt

輸出應為: cbrt 8 sqrt 9 +

例3:

輸入: 5 + 4 - 9 / 2 ^ 6 * cbrt ( 8 )

輸出: 5 4 + 9 2 6 ^ / 8 cbrt * -

輸出應為: 5 4 + 9 2 6 ^ / cbrt 8 * -

想一想。 分流碼算法將中綴轉換為后綴。 不過這個:

cbrt ( 8 )

不是中綴表達式。 它是前綴表達式。

作為后綴表達式,它看起來像這樣:

8  cbrt

它作為一個中綴表達式可能看起來像留給讀者的練習,但它不是你開始的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM