Android基础实战--实现简单计算器包含复合运算(下)


Android基础实战–实现简单计算器包含复合运算(下)

声明:
简书内容同步:https://www.jianshu.com/u/90ce902439cc
1.本文章为原创文章,转载注明出处,蟹蟹~
2.初学安卓,水平有限,还有很多不足和应当修正的地方,欢迎评论指点

这是简单计算器上篇链接,本文主要概述自己表达式式求值的两种方法:LinkedList和Stack,思路过程极为相似,只是换了一种存储方式。先简单小结LinkedList和Stack的使用。
LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList的本质是双向链表。
在此列出几个常用方法:

void add(int index,E element)   
 //在此列表中指定位置插入元素,未指定位置则默认在末尾

void addFirst(Object o)
//将指定元素插入列表首部

void addLast(Object o)
//将指定元素插入列表尾部

Object getFirst()
//返回列表首元素

Object getLast()
//返回列表尾部元素

Object removeFirst()
//移除并返回列表首元素

Object removeLast()
//移除并返回列表尾部元素

更多详细用法请查阅API或搜索相关文章,下面这网址挺详细的,推荐一下:
Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
栈的总结就很简易了,方法不多:

void push(Object o)    //添加元素

Object pop()             //删除并返回最后添加的元素(即栈顶元素)

boolean isEmpty()      //判断是否为空

int size()             //返回栈中元素个数

Object peek()        //返回栈顶元素

###运算处理过程
接着上篇文章内容之后就是利用上篇文章中表达式分离后的数据:存放运算数的list集合numl,以及存放运算符的字符串strsign
两种方法最终效果图如下:
eclipse调式两种解法
####栈解法
准备工作就是定义两个栈,一个放运算符,一个放运算数。两个下标,对应运算数的list集合numl,以及存放运算符的字符串strsign两者的下标。后面的char和两double类型的变量即参与运算时暂时存放数据的变量。还有一个获取优先级函数(其中我将左右括号和等于均视为操作符,优先级数具体在函数中见)。具体如下:

//获取优先级函数
	  public  int  getValue(char a) {
	         int value=0;
	         switch(a){
	             case '=':value =0;break;
	             case ')':value =1;break;
	             case '(':value =3;break;
	             case '+':value =1;break;
	             case '-':value =1;break;
	             case '*':value =2;break;
	             case '/':value =2;break;
	         }
	         return value;
	     }
//利用分离的数据:numl的list集合,以及strsign字符串
	        Stack<Character> ops = new Stack<Character>();
	        Stack<Double> vals   = new Stack<Double>();
	        int i = 0;// 操作数集合numl下标
	        int j = 0;// 操作符strsign字符串下标
	        char symbol;// 符号
	        double numone, numtwo;// 符号前后两个数	

//事先将‘=’和第一个操作数压到相应栈中
 if(ops.isEmpty()) {
        		ops.push('=');
        		vals.push(numl.get(i++));
        	}

总体思路即遍历整个操作符strsign和集合numl,通过两个暂存操作数和操作符的栈,根据优先级提取运算数和运算符进行运算,优先级大于前面的运算符就压栈不进行运算,优先级小于等于运算符栈栈顶元素优先级则计算,将结果继续暂存至栈中,直至遍历到strsign末尾(即等号),其运算结果就是此时运算数栈的栈顶元素。

具体过程大致如下:

while(!(strsign.charAt(j)=='='&&ops.peek()=='=')){	       	
	  //比较符号优先级,当前符号优先级大于前一个则压栈	        	
	        	if( getValue(strsign.charAt(j))>getValue(ops.peek()) ) {	        		
	        	     if(strsign.charAt(j)=='(') {
	        	    	 ops.push(strsign.charAt(j++));
	        	    	 continue;
	        	     }
	        	     vals.push(numl.get(i++));
	        	     ops.push(strsign.charAt(j++));
	        	}
	        	//若小于等于当前运算符优先级
	        	else{
                                 //过滤括号	        		
	        		if(strsign.charAt(j)==')'&&ops.peek()=='(') {	        			
	        			j++;
	        			ops.pop();//)不进栈且(出栈   此种情况是括号内运算完之后仅剩一个数
	        			continue;  			
	        		}
	        		if(ops.peek()=='(') {
	        			//紧接着左括号的运算符,直接正常压栈
	        			vals.push(numl.get(i++));
	        			ops.push(strsign.charAt(j++));
	        			continue;
	        		}
	        		//其他情况直接出栈参与运算(右括号,和同等优先级的运算符)
                    //运算过程省略
           }

运算过程即从操作数栈弹出两个数,操作符中弹出一个操作符,根据操作符对这两个数进行运算即可。运算时需要注意的是先出栈的是后面那一个操作数,即后进先出。运算完后将结果压到操作数中即可。通过这样的while循环过后最终结果即操作数栈中的栈顶元素了。
###LinkedList解法
看文章开始时的总结就不难发现,Stack能做的事情LinkedList都能做,两者的方法完全可以做个类比来等效操作:
比如:

//移除并返回列表尾部元素
Object removeLast()     //LinkedList
Object pop()             //Stack

//添加元素至尾部
void push(Object o)    //LinkedList
void addLast(Object o) //Stack

//返回列表首元素
Object getFirst()   //LinkedList
Object peek()        //Stack

因此确实如上篇文章结尾处所言,过程几乎一致,只是换了一种存储类型罢了,其实我一开始就是用的LinkedList来解的,多写一种解法只是顺便复习一下数据结构。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值