下面看其一个转换的例子(取自维基百科):
按照算法逻辑,我们可以将2+3*5-6转换成235*+6-。
输入:中缀表达式s
输出:计算结果result
算法calculateInfixExp(s):
start 遍历s中所有的字符c,
如果c = ‘(’,则 str = str +c until c = ‘)’;
calResult = calculateInfixExp(str);
num_stack.push(calResult);
如果c为数字符号,则num_stack.push(c);
如果c为计算符号,c的优先级小于或等于栈顶计算符号,则
start 遍历operator_stack,
计算符号 = operator_stack.pop();
n1 = num_stack.pop();
n2 = num_stack.pop();
num_stack.push(n1 计算符号 n2);
如果 c的next为null,则 operator_stack.push(c);
end 遍历operator_stack
end 遍历s中所有的字符c
public class Calculator extends Activity {
final String[] buttonStrings = new String[]
{
"7", "8", "9", "+",
"4", "5", "6", "-",
"1", "2", "3", "*",
".", "0", "=", "/"
};
private boolean isOperator(String str) {
if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/") || str.equals("=")) {
return true;
}
return false;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calculator);
//得到屏幕的size
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
int oneQuarterWidth = (int) (size.x * 0.25);
GridLayout gridLayout = (GridLayout) findViewById(R.id.root);
Button btn = null;
for (int i = 0; i < buttonStrings.length; ++i) {
btn = new Button(this);
btn.setText(buttonStrings[i]);
btn.setTextSize(40);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Button button = (Button) view;
TextView showView = (TextView) findViewById(R.id.showView);
//如果含有等号则输入其他字符时清楚显示数字
if (showView.getText().toString().contains("=")) {
showView.setText("");
}
//这里仅实现简单的容错处理:1、首字母不能为计算符号
if (showView.getText().toString().isEmpty() && isOperator(button.getText().toString())) {
return;
}
//2、尾字母不能为计算符号
if (button.getText().equals("=") && isOperator(String.valueOf(showView.getText().charAt(showView.getText().length() - 1)))) {
return;
}
// 3、不能出现连续的计算符号
if (showView.getText().length() > 1 && isOperator(String.valueOf(showView.getText().charAt(showView.getText().length() - 1)))
&& isOperator(button.getText().toString())) {
return;
}
//处理显示和计算逻辑
if (!button.getText().equals("=")) {
showView.append(button.getText());
} else {
showView.setText(showView.getText().toString() + "=" + String.valueOf(CalculatorAlgorithm.calculateInfixExp(showView.getText().toString())));
}
}
});
GridLayout.Spec rowSpec = GridLayout.spec(i / 4 + 2);
GridLayout.Spec colSpec = GridLayout.spec(i % 4);
GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(rowSpec, colSpec);
layoutParams.width = oneQuarterWidth;
gridLayout.addView(btn, layoutParams);
}
//绑定清除屏幕数字方法
Button clearBtn = (Button) findViewById(R.id.clear);
clearBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
TextView showView = (TextView) findViewById(R.id.showView);
showView.setText("");
}
});
//绑定回退键方法
Button backBtn = (Button) findViewById(R.id.back);
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
TextView showView = (TextView) findViewById(R.id.showView);
if(!showView.getText().toString().isEmpty())
{
showView.setText(showView.getText().toString().substring(0,showView.getText().length()-1));
}
}
});
}
}
(3)算法类
/**
* Created by ZH on 2014/12/1.
*/
public class CalculatorAlgorithm {
private static Map operatorPriority = new HashMap();
static {
//符号对应的数值越高则优先级越高
operatorPriority.put("+", 10);
operatorPriority.put("-", 10);
operatorPriority.put("*", 20);
operatorPriority.put("/", 20);
}
/**
* 中缀表达式转后缀表达式的并计算出结果
*
* @param infixExp
* @return
*/
public static Double calculateInfixExp(String infixExp) {
if (null == infixExp || infixExp.isEmpty()) {
return null;
}
char c;
int subStart = 0;
StringBuilder numBuf = new StringBuilder();
//存放数字的栈
Stack numStack = new Stack();
//存放计算符的栈 1-0.5*(3.5-1.5)-5.3
Stack operatorStack = new Stack();
for (int i = 0; i < infixExp.length(); ) {
c = infixExp.charAt(i);
//先处理含括号的场景
if ('(' == c) {
subStart = infixExp.indexOf(')', i);
numStack.push(calculateInfixExp(infixExp.substring(i + 1, subStart)));
i = subStart + 1;
continue;
}
//如果是数字
if (String.valueOf(c).matches("[0-9.]")) {
numBuf.append(c);
//最后一个字符若是数字则直接入栈
if (infixExp.length() == (i + 1)) {
numStack.push(Double.valueOf(numBuf.toString()));
}
} else
//如果是计算符号
{
//若前一个字符为右括号,则当前字符肯定为计算符号,因此不入数字栈
if (')' != infixExp.charAt(i - 1)) {
numStack.push(Double.valueOf(numBuf.toString()));
numBuf = new StringBuilder();
}
//当前的优先级小于或等于栈顶的
if (!operatorStack.isEmpty() && operatorPriority.get(String.valueOf(c)) < operatorPriority.get(operatorStack.peek().toString())) {
popOperation(numStack, operatorStack);
}
operatorStack.push(c);
}
//最后一个字符
if (infixExp.length() == (i + 1)) {
popOperation(numStack, operatorStack);
}
++i;
}
return numStack.pop();
}
/**
* 处理数字和计算符号进行计算并将结果入栈
* @param numStack
* @param operatorStack
*/
private static void popOperation(Stack numStack, Stack operatorStack) {
char top;
double num1 = 0;
double num2 = 0;
while (!operatorStack.isEmpty()) {
top = operatorStack.pop();
num1 = numStack.pop();
num2 = numStack.pop();
numStack.push(calculate(top, num2, num1));
}
}
/**
* 根据计算符号oper对n1和n2进行计算,并返回double型结果
* @param oper
* @param n1
* @param n2
* @return
*/
private static double calculate(char oper, double n1, double n2) {
switch (oper) {
case '+':
return n1 + n2;
case '-':
return n1 - n2;
case '*':
return n1 * n2;
case '/':
if (0 == n2) {
return 0;
}
return n1 / n2;
default:
return 0;
}
}
}