思路:
计算器的简单实现
实现计算机的加、减、乘、除操作
eg:3+2*4-20/4 = 3+8-5 = 6
1.定义index对表达式进行扫描; 创建两个栈,一个栈存放数字,称为数栈(numStack);一个栈存放符号,称为符号栈(symbolStack);
2.当遇到数字时,入数栈;(注意字符位数,数字有可能是多位数)
2.1若是字符串最后一个的时候,直接入数栈
2.2若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈
3.当遇到符号时,入符号栈
3.1如果符号栈为空,则直接入栈
3.2如果符号栈不为空;则需要判断优先级;
3.2.1判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,
同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。
3.2.2若优先级大于前一个符号,则继续进行入栈操作
4.当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果
- 实现栈的基本功能,先进后出,栈的插入、删除(返回栈顶并删除栈顶元素)、以及返回栈的栈顶操作(不删除栈顶元素)
class ArrayStack1<E>{ // 头插法时间复杂度为o(n), 尾插尾删的时间复杂度为O(1).
private E[] Array;
private int top; //有效个数
private static final int INITSIZE = 4;
public ArrayStack1() {
Array = (E[])new Object[INITSIZE];
}
public boolean isEmpty(){
return top == 0;
}
// 栈插入元素
public void push(E value) { //插入
//top从0开始,插入元素后有效个数加1,当top == INITSIZE时,说明栈满,扩容
Array[top] = value;
top++;
if (top == INITSIZE) {
Array = Arrays.copyOf(Array, Array.length + (Array.length >> 1));
}
}
//从栈顶删除元素
public E pop() { //删除
if (top == 0) {
return null;
}
E Top = Array[top-1];
Array[--top] = null;
return Top;
// Array[top -1] = null;
// top--;
}
// 获取栈顶元素
public E peek() { //获取栈顶元素
if (top == 0) {
throw new EmptyStackException(); // 空栈异常
}
return Array[top - 1];
}
- 判断扫描到的字符是否为 + - * /这四种操作
public boolean isSymbol(char value){
return value == '+'|| value == '-'|| value == '*' || value == '/';
- 判断优先级的大小,操作符优先级由程序员掌控,返回值越大,优先级越高
public int priority(char symbol){
if(symbol == '*' || symbol == '/'){
return 1;
}else if(symbol == '+'||symbol == '-'){
return 0;
}else {
return -1;
}
}
- + - * / 的运算过程,num1 num2 symbol 三个变量,注意num1 和 num2 的先后顺序
public float method(float num1,float num2,char symbol) {
float res = 0;
switch (symbol) {
case ('+'):
res = num1 + num2;
break;
case ('-'):
res = num2 - num1;
break;
case ('*'):
res = num1 * num2;
break;
case ('/'):
res = num2 / num1;
break;
default:
break;
}
return res;
}
- 计算过程,根据上述思路,进行计算的过程
public void CountMethod(String str,ArrayStack1 numStack,ArrayStack1 symbolStack){
int index = 0; // 用来遍历表达式
float num1 = 0;
float num2 = 0;
char symbol = 0;
char ch = 0; // 用来存放遍历的字符
float res = 0;
String keepCh = ""; // 用作多位数字的字符拼接
while(true){
// 得到字符串的字符
ch = str.substring(index,index+1).charAt(0);
// 当遇到符号时,入符号栈
if(symbolStack.isSymbol(ch)){
// 如果符号栈为空,则直接入栈
if(symbolStack.isEmpty()){
symbolStack.push(ch);
index++;
}else{
// 判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,
// 同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。
// 若优先级大于前一个符号,则继续进行入栈操作
if(symbolStack.priority(ch) < symbolStack.priority((char) symbolStack.peek())){
symbol = (char)symbolStack.pop();
num1 = (float)numStack.pop();
num2 = (float) numStack.pop();
res = symbolStack.method(num1,num2,symbol);
numStack.push(res);
}else{
symbolStack.push(ch);
index++;
}
}
}else{
keepCh += ch;
// 当遇到数字时,入数栈;
// 若是字符串最后一个的时候,直接入数栈
// 若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈
if(index == str.length()-1) {
numStack.push((float)Integer.parseInt(keepCh));
index++;
}else{
while (true) {
ch = str.substring(index + 1, index + 2).charAt(0);
if (symbolStack.isSymbol(ch)) { // 下一个是符号,则入栈
numStack.push((float)Integer.parseInt(keepCh));
keepCh = "";
index++;
break;
}
keepCh += ch;
index++;
}
}
}
if(index >= str.length()){ //
break;
}
}
//当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果(symbolStack为空)
while (true){
if(symbolStack.isEmpty()){
break;
}
symbol = (char)symbolStack.pop();
num1 = (float)numStack.pop();
num2 = (float) numStack.pop();
res = symbolStack.method(num1,num2,symbol);
numStack.push(res);
}
}
- 测试代码
public static void main(String[] args) {
// 输入表达式
String str = "32+245*4-20/5";
// 创建数栈和符号栈
ArrayStack1 numStack = new ArrayStack1();
ArrayStack1 symbolStack = new ArrayStack1();
numStack.CountMethod(str,numStack,symbolStack);
System.out.println("表达式:"+str+"="+numStack.peek());
}
- 测试结果
- 完整代码:(已测,运行成功)
import java.util.Arrays;
import java.util.EmptyStackException;
public class Calculator { // 利用中缀表达式
public static void main(String[] args) {
// 输入表达式
String str = "32+245*4-20/5";
// 创建数栈和符号栈
ArrayStack1 numStack = new ArrayStack1();
ArrayStack1 symbolStack = new ArrayStack1();
numStack.CountMethod(str,numStack,symbolStack);
System.out.println("表达式:"+str+"="+numStack.peek());
}
}
class ArrayStack1<E>{ // 头插法时间复杂度为o(n), 尾插尾删的时间复杂度为O(1).
private E[] Array;
private int top; //有效个数
private static final int INITSIZE = 4;
public ArrayStack1() {
Array = (E[])new Object[INITSIZE];
}
public boolean isEmpty(){
return top == 0;
}
// 栈插入元素
public void push(E value) { //插入
//top从0开始,插入元素后有效个数加1,当top == INITSIZE时,说明栈满,扩容
Array[top] = value;
top++;
if (top == INITSIZE) {
Array = Arrays.copyOf(Array, Array.length + (Array.length >> 1));
}
}
//从栈顶删除元素
public E pop() { //删除
if (top == 0) {
return null;
}
E Top = Array[top-1];
Array[--top] = null;
return Top;
// Array[top -1] = null;
// top--;
}
// 获取栈顶元素
public E peek() { //获取栈顶元素
if (top == 0) {
throw new EmptyStackException(); // 空栈异常
}
return Array[top - 1];
}
public void show(){
for(int i = 0;i < Array.length;i++){
if(Array[i] != null) {
System.out.println("栈内元素为" + Array[i] + " ");
}
}
}
/**
*
* @param value 输入一个字符,判断当前符号是数字还是符号
* @return 返回 true ,是符号
*/
public boolean isSymbol(char value){
return value == '+'|| value == '-'|| value == '*' || value == '/';
}
/**
* 判断优先级的大小,操作符优先级由程序员掌控
* @param symbol
* @return 返回值越高优先级越大
*/
public int priority(char symbol){
if(symbol == '*' || symbol == '/'){
return 1;
}else if(symbol == '+'||symbol == '-'){
return 0;
}else {
return -1;
}
}
/**
* 运算方式
* @param num1 数字1
* @param num2 数字2
* @param symbol 操作符号
* @return 操作结果
*/
public float method(float num1,float num2,char symbol) {
float res = 0;
switch (symbol) {
case ('+'):
res = num1 + num2;
break;
case ('-'):
res = num2 - num1;
break;
case ('*'):
res = num1 * num2;
break;
case ('/'):
res = num2 / num1;
break;
default:
break;
}
return res;
}
public void CountMethod(String str,ArrayStack1 numStack,ArrayStack1 symbolStack){
int index = 0; // 用来遍历表达式
float num1 = 0;
float num2 = 0;
char symbol = 0;
char ch = 0; // 用来存放遍历的字符
float res = 0;
String keepCh = ""; // 用作多位数字的字符拼接
while(true){
// 得到字符串的字符
ch = str.substring(index,index+1).charAt(0);
// 当遇到符号时,入符号栈
if(symbolStack.isSymbol(ch)){
// 如果符号栈为空,则直接入栈
if(symbolStack.isEmpty()){
symbolStack.push(ch);
index++;
}else{
// 判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,
// 同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。
// 若优先级大于前一个符号,则继续进行入栈操作
if(symbolStack.priority(ch) < symbolStack.priority((char) symbolStack.peek())){
symbol = (char)symbolStack.pop();
num1 = (float)numStack.pop();
num2 = (float) numStack.pop();
res = symbolStack.method(num1,num2,symbol);
numStack.push(res);
}else{
symbolStack.push(ch);
index++;
}
}
}else{
keepCh += ch;
// 当遇到数字时,入数栈;
// 若是字符串最后一个的时候,直接入数栈
// 若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈
if(index == str.length()-1) {
numStack.push((float)Integer.parseInt(keepCh));
index++;
}else{
while (true) {
ch = str.substring(index + 1, index + 2).charAt(0);
if (symbolStack.isSymbol(ch)) { // 下一个是符号,则入栈
numStack.push((float)Integer.parseInt(keepCh));
keepCh = "";
index++;
break;
}
keepCh += ch;
index++;
}
}
}
if(index >= str.length()){ //
break;
}
}
//当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果(symbolStack为空)
while (true){
if(symbolStack.isEmpty()){
break;
}
symbol = (char)symbolStack.pop();
num1 = (float)numStack.pop();
num2 = (float) numStack.pop();
res = symbolStack.method(num1,num2,symbol);
numStack.push(res);
}
}
}