[数据结构与算法(java)](中缀表达式)计算器功能全面

第一次发博客哈,如有问题请多多指教~~

简单介绍一下此计算器:

计算器采用中缀表达式(正常书写的表达式),可计算小数,多位数,负数,以及带括号的运算

含有去除空白等符号的功能

主要介绍一下实现的思路:

1)先输入一个中缀表达式,不带空格,可使用正则表达式去除多余干扰(如空格)

2) 定义变量,对表达式进行遍历

3)对表达式进行遍历,遍历为数字和符号两种情况(括号单说)。数字(多位数)(小数)进行字符串拼接,最后转化为数字;符号比较优先级,进行相应操作(代码中有注释)(下图中因考虑到从左到右计算原则,3.2小于或等于改为小于)

4)如果是括号,'('直接压入栈,')'则计算栈中数据,直到'(',将其弹出。计算思路如图4

5)遍历结束,输出最后值,这个值就是数栈中剩的一个值

代码可以使用自带Stack,仅声明最后几个方法也可(pri(),isoper(),cl()),本代码使用数组模拟栈,更好理解底层思维。代码也可以申请两个栈,不用单独对字符写方法。

自定义Stack如下

//定义栈
class Astack2
{
	private int num;        //栈值
	private double[] sk1;    //存储栈值
	private char[] sk2;     //存储符号
	private int top = -1;   //存储栈顶值,默认为-1
	private int top2 = -1;   //存储栈顶值,默认为-1
	
	//构造器
	public Astack2(int num)
	{
		this.num = num;
		sk1 = new double[num];
		sk2 = new char[num];
	}
	
	//清除数据(到结束或者到'('处)
	public void clear()
	{
		while(true)
		{
			if(ischarempty())
				break;
	
			if(peek() == '(')
			{
				popchar();
				break;
			}
			
			double k = 0;
			k = cla(pop(),pop(),popchar());
			push(k);
		}
	}
	//判断是否为空
	public boolean isempty()
	{
		 return top == -1;
	}
	
    //判断符号是否为空
	public boolean ischarempty()
	{
		 return top2 == -1;
	}
	
	//判断是否为满
	public boolean isfull()
	{
		 return top == num - 1;
	}
	
	//入栈
	public void push(double i)
	{
		if(isfull())
		{
			System.out.println("栈满~~");
			return;
		}
		
		top++;
		sk1[top] = i;
	}
	
	//入栈(符号)
	public void pushchar(char i) 
	{
		if (isfull()) 
		{
			System.out.println("栈满~~");
			return;
		}

		top2++;
		sk2[top2] = i;
	}

	//查看栈顶符号
	public char peek()
	{
		return sk2[top2];
	}
	
	//出栈
	public double pop()
	{
		if(isempty())
		{
			return 0;
		}
		
		top--;
		return sk1[top+1];
	}
	
	//弹出符号
	public char popchar()
	{
		top2--;
		return sk2[top2+1];
	}
	
	
	//返回优先级
	public int pri(int a)
	{
		if(a == '+' || a == '-')
			return 0;
		if(a == '*' || a == '/')
			return 1;	
		if(a == '(')
			return -1;
		
		return -1;
	}
	
	//判断是否为运算符
	public boolean isoper(int i)
	{
	     return i == '+' || i == '-' || i == '*' || i == '/' || i == '(' || i == ')';	
	}
	
	//运算方式
	public double cla(double i,double j,int k)
	{
		double res = 0;
		switch(k)
		{
		case '+':
			res = i + j;
		    break;
		
		case '-':
			res = j - i;
			break;
		
		case '*':
			res = i * j;
			break;
		
		case '/':
			res = j / i;
			break;
			
		default:
			break;
		}
		
		return res;
	}
}

完成整代码如下: 

package Stack;

import java.util.Scanner;

//计算加减乘除,小数,负数,带括号
//去除空格,可使用正则表达式

public class StcakCalculator 
{
	public static void main(String[] args) 
	 {
		System.out.println("请输入算式:");
		Scanner in = new Scanner(System.in);
		String expre = in.nextLine();
		
		//  \\s+匹配任意空白字符
		String express = expre.replaceAll("\\s+","");
		
		
		//创建两个栈,一个存放数据,一个存放符号
		Astack2 sk = new Astack2(10);
		
	    //定义遍历辅助值
		int tem = 0;   //遍历字符串,相当图中指针
		double tem1 = 0;  
		double tem2 = 0;  
		
		boolean i = false;    //将负数转换为正数
		boolean j = false;     //区分(-1+2) 和 (1-2)
		double res = 0;  //返回值,暂存数据
		char ch;       //存放扫描所得的数字
		String total = "";   //多位数使用
		
		while(true)
		{
			ch = express.substring(tem,tem + 1).charAt(0);     //将字符串第一位转化为字符
			if(ch == '-')        //特判,以免第一位就是符号,如 -1+2
			{
                i = true;
                j = true;
            }
			
			if(sk.isoper(ch))   //判断是否为符号和()
			{
				if(sk.ischarempty() || (sk.peek() == '(' && j))   //栈顶为(,且下一个符号为-
				{
					if(i)       //特判符号
						sk.push(0);
					sk.pushchar(ch);
				}
				else
				{
					if(ch == ')')
						sk.clear();
					else if(ch == '(')
						sk.pushchar(ch);
				    else if(sk.pri(ch) > sk.pri(sk.peek()))       //优先级大于,直接入栈
						sk.pushchar(ch);
					else       //优先级小于,运算
					{
						tem1 = sk.pop();
						tem2 = sk.pop();
						res = sk.cla(tem1, tem2, sk.popchar());   //计算函数
						sk.push(res);
						sk.pushchar(ch);
					}
				}
			}
			else         //为数据
			{
				total += ch;       //多位数,小数拼接
				//如果到最后一位
				if(tem >= express.length() - 1)
					sk.push(Double.parseDouble(total));
				else
				{
					if(sk.isoper(express.substring(tem + 1, tem + 2).charAt(0)))
					{
						sk.push(Double.parseDouble(total));
						j = false;
						i = false;
						total = "";
					}
				}
				
			}
			
			tem++;          //向后遍历
			if(tem >= express.length())
				break;
		}
		//当遍历完成后,对栈中剩存的数据和符号操作
		sk.clear();
		in.close();
		System.out.printf("%.5f",sk.pop());
	}
}

//定义栈
class Astack2
{
	private int num;        //栈值
	private double[] sk1;    //存储栈值
	private char[] sk2;     //存储符号
	private int top = -1;   //存储栈顶值,默认为-1
	private int top2 = -1;   //存储栈顶值,默认为-1
	
	//构造器
	public Astack2(int num)
	{
		this.num = num;
		sk1 = new double[num];
		sk2 = new char[num];
	}
	
	//清除数据(到结束或者到'('处)
	public void clear()
	{
		while(true)
		{
			if(ischarempty())
				break;
	
			if(peek() == '(')
			{
				popchar();
				break;
			}
			
			double k = 0;
			k = cla(pop(),pop(),popchar());
			push(k);
		}
	}
	//判断是否为空
	public boolean isempty()
	{
		 return top == -1;
	}
	
    //判断符号是否为空
	public boolean ischarempty()
	{
		 return top2 == -1;
	}
	
	//判断是否为满
	public boolean isfull()
	{
		 return top == num - 1;
	}
	
	//入栈
	public void push(double i)
	{
		if(isfull())
		{
			System.out.println("栈满~~");
			return;
		}
		
		top++;
		sk1[top] = i;
	}
	
	//入栈(符号)
	public void pushchar(char i) 
	{
		if (isfull()) 
		{
			System.out.println("栈满~~");
			return;
		}

		top2++;
		sk2[top2] = i;
	}

	//查看栈顶符号
	public char peek()
	{
		return sk2[top2];
	}
	
	//出栈
	public double pop()
	{
		if(isempty())
		{
			return 0;
		}
		
		top--;
		return sk1[top+1];
	}
	
	//弹出符号
	public char popchar()
	{
		top2--;
		return sk2[top2+1];
	}
	
	
	//返回优先级
	public int pri(int a)
	{
		if(a == '+' || a == '-')
			return 0;
		if(a == '*' || a == '/')
			return 1;	
		if(a == '(')
			return -1;
		
		return -1;
	}
	
	//判断是否为运算符
	public boolean isoper(int i)
	{
	     return i == '+' || i == '-' || i == '*' || i == '/' || i == '(' || i == ')';	
	}
	
	//运算方式
	public double cla(double i,double j,int k)
	{
		double res = 0;
		switch(k)
		{
		case '+':
			res = i + j;
		    break;
		
		case '-':
			res = j - i;
			break;
		
		case '*':
			res = i * j;
			break;
		
		case '/':
			res = j / i;
			break;
			
		default:
			break;
		}
		
		return res;
	}
}

还有逆波兰表达式(思路清晰):逆波兰表达式 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
做一门精致,全面详细的 java数据结构与算法!!!让天下没有难学的数据结构,让天下没有难学的算法,不吹不黑,我们的讲师及其敬业,可以看到课程视频,课件,代码的录制撰写,都是在深夜,如此用心,其心可鉴,他不掉头发,谁掉头发???总之你知道的,不知道的,我们都讲,并且持续更新,走过路过,不要错过,不敢说是史上最全的课程,怕违反广告法,总而言之,言而总之,这门课你值得拥有,好吃不贵,对于你知识的渴求,我们管够管饱话不多说,牛不多吹,我们要讲的本门课程内容:稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值