我正在尝试使用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 * -
答案 0 :(得分:2)
想一想。分流码算法将中缀转换为后缀。但是这个:
.bash_profile
不是中缀表达式。它是前缀表达式。
作为后缀表达式,它看起来像这样:
cbrt ( 8 )
作为中缀表达的内容可能会留作读者的练习,但它并不是你的开始。