简单的计算器程序却蕴涵的有趣的数据结构
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                简单的计算器程序却蕴涵的有趣的数据结构
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.                        
                                ????????入門學(xué)習(xí)java 或者c的時(shí)候,加減乘除計(jì)算器是必不可少的,switch 配合上+-*/ 完成簡(jiǎn)易計(jì)算器的制作,再入門點(diǎn)的可以套一個(gè)ui架子,完成兩個(gè)數(shù)字加減乘除,但是對(duì)于多個(gè)數(shù)字的加減乘除來(lái)說(shuō),程序就比較復(fù)雜了。我推薦兩種有趣的算法來(lái)完成多個(gè)數(shù)字的加減乘除,優(yōu)先級(jí)等等。逆波蘭算法和雙棧
逆波蘭算法如下,注釋我也直接嵌入到其中,方便復(fù)制的時(shí)候理解,下面的算法都是寫的工具類,只需要將參數(shù)傳入進(jìn)去即可!
/*** Date:2021/10/23* Description:代碼版權(quán)聲明 實(shí)現(xiàn)逆波蘭計(jì)算器* 代碼思路* 先將表達(dá)式轉(zhuǎn)換為逆波蘭表達(dá)式 步驟如下* 1.如果遇到‘(’ 直接入S1* 2.如果遇到數(shù)字直接壓入S2* 3.如果遇到‘)’,將S1棧頂距離最近知道‘(’元素依次彈出并依次壓入S2* 4. 如果遇到符號(hào)X , X的優(yōu)先級(jí)大于S1棧頂X壓入S1,X的優(yōu)先級(jí)小于或等于S1棧頂進(jìn)行如下操作* S1彈出棧頂元素,并壓入S2,直到X優(yōu)先級(jí)大于S1棧頂元素或者該元素為‘(’,再將X壓入S1* 5.遍歷結(jié)束之后看S1是否為空,若不為空,依次將S1元素彈出并壓入S2* <p>* <p>* <p>* 逆波蘭表達(dá)式計(jì)算結(jié)果代碼思路如下* <p>* 從左到右依次遍歷 定義一個(gè)stack即可* 如果是數(shù)字,直接壓棧,* 如果是符號(hào)(不是數(shù)字),則出棧兩次,第一次出棧定義為b ,第二次出棧a ,然后 a opa b* 棧中剩下一個(gè)元素就是結(jié)果*/ public class PolandClient {//該字符是否為數(shù)字private static boolean isNum(char x) {if (x >= '0' && x <= '9' || x == '.') {return true;} else return false;}//獲取符號(hào)的優(yōu)先級(jí)private static int getPor(char opera) {int por = 0;if (opera == '+') {por = 1;}if (opera == '-') {por = 1;}if (opera == '*') {por = 3;}if (opera == '/') {por = 3;}return por;}//逆波蘭表達(dá)式轉(zhuǎn)換public ArrayList<String> getPolandString(String cirString) {Stack<String> s1; //定義兩個(gè)棧 一個(gè)符號(hào)棧S1 一個(gè)操作棧S2Stack<String> s2;String cir = cirString;char[] chars = cir.toCharArray(); //將表達(dá)式轉(zhuǎn)換成字節(jié) 依次遍歷s1 = new Stack<>();//將棧實(shí)例化s2 = new Stack<>();int index = 0;//索引 作用能夠遍歷表達(dá)式 1+21+3while (true) { //進(jìn)行遍歷int index0 = index;//如果數(shù)字大于10,就會(huì)用到index0 為了后面遇見(jiàn)數(shù)字的時(shí)候 標(biāo)志索引StringBuilder stringBuilder = new StringBuilder(); // 多次追加數(shù)字 用該類比較方便if (index == cir.length()) { //遍歷到滿足此條件時(shí)候 跳出循環(huán) 判斷跳出循環(huán)break;} else if (isNum(chars[index0])) { //是數(shù)字的情況下進(jìn)行 進(jìn)行如下操作while (index0 != cir.length() && isNum(chars[index0])) {//后面那個(gè)還是數(shù)字進(jìn)行如下操作//是數(shù)字的話追加stringBuilder.append(chars[index0]); //追加index++;//指標(biāo)后移index0++;//后移}index--;s2.push(stringBuilder.toString());//將結(jié)果入棧} else if (chars[index] == '(') {//如果遍歷到的字符是左括號(hào)stringBuilder.append(chars[index]);//追加s1.push(stringBuilder.toString());//入棧 StringBuilder} else if (chars[index] == ')') {//如果遍歷到的字符是右括號(hào) 進(jìn)行如下操作while (true) {//將s1元素出棧,并入s2棧,(前提條件是如若s1出棧的符號(hào)是左括號(hào),就將左括號(hào)出棧,循環(huán)結(jié)束)(s1為空棧 同樣結(jié)束循環(huán))if (!s1.isEmpty()) {//如果s1不是空的String pop = s1.pop();//出棧 判斷if (pop.equals("(")) {//若它是左括號(hào) 循環(huán)結(jié)束break;} else {//否則 入s2棧s2.push(pop);}} else {break;}}//如下是 遍歷到運(yùn)算符的時(shí)候} else if (chars[index] == '+' || chars[index] == '-' || chars[index] == '*' || chars[index] == '/') {if (s1.isEmpty() || getPor(chars[index]) > getPor(s1.peek().toCharArray()[0])) {//如果s1為空或者該優(yōu)先級(jí)大于S1棧頂優(yōu)先級(jí)stringBuilder.append(chars[index]);//追加s1.push(stringBuilder.toString());//s1入棧 //"1-2/2*3+4" // System.out.println(stringBuilder.toString()+"我的-號(hào)");} else if (getPor(chars[index]) <= getPor(s1.peek().toCharArray()[0])) {//如果該優(yōu)先級(jí) 小于等于s1中優(yōu)先級(jí),進(jìn)行如下操作while (true) {if (!s1.isEmpty()) {//先判斷是否為空String pop = s1.pop(); //彈出S1棧頂元素if (pop.equals("(") || getPor(chars[index]) > getPor(pop.toCharArray()[0])) {//判斷出棧元素是否為左括號(hào) 是s1.push(pop);break;} else if (getPor(chars[index]) <= getPor(pop.toCharArray()[0])) {s2.push(pop); //否則入S2System.out.println(pop);}} else {break;}}stringBuilder.append(chars[index]);s1.push(stringBuilder.toString());}}index++;//索引后移}//遍歷結(jié)束后 對(duì)S1判空循環(huán) 依次將S1元素彈出并壓入S2while (!s1.isEmpty()) {String pop = s1.pop();s2.push(pop);}//最后s2依次彈出放S1 ,這樣s1出棧的順序就是原表達(dá)式的后綴表示了(逆波蘭)ArrayList<String> list = new ArrayList<>();//實(shí)例化了一個(gè)返回集合while (!s2.isEmpty()) {list.add(s2.pop()); // 12 21逆序}Collections.reverse(list);System.out.println(Arrays.asList(list));return list;}//ab+cd- 將逆波蘭表達(dá)式轉(zhuǎn) 計(jì)算出結(jié)果public double getAnswer(ArrayList<String> list) {//參數(shù)是 逆波蘭棧Stack<String> s1 = new Stack<>();for (int i = 0; i < list.size(); i++) {String c = list.get(i); //運(yùn)算棧if (isNum(c.toCharArray()[0])) {s1.push(c);} else {String second = s1.pop();//2String first = s1.pop();//1double answer = getAnswer(Double.parseDouble(first), Double.parseDouble(second), c);s1.push(answer + "");}}if (!s1.isEmpty()) {String pop = s1.pop();return Double.parseDouble(pop);} else {return 0;}}public double getAnswer(double a, double b, String c) {double answer = 0;if (c.equals("+")) {answer = a + b;} else if (c.equals("-")) {answer = a - b;} else if (c.equals("*")) {answer = a * b;} else if (c.equals("/")) {answer = a / b;}return answer;}}雙棧算法代碼如下。
/*** 這是一個(gè)全能計(jì)算器代碼* 具體思路如下* 1.建立兩個(gè)棧,分別是 數(shù)字棧 和符號(hào)棧* 2.從左到有依次遍歷表達(dá)式* 3.如果遇到數(shù)字,將數(shù)字入數(shù)字棧* 4.如果遇到符號(hào),分兩種情況,若符號(hào)棧為空,該符號(hào)直接入符號(hào)棧* 5.若符號(hào)棧不為空--繼續(xù)判斷該符號(hào)的優(yōu)先級(jí)是否小于或等于該棧頂符號(hào)優(yōu)先級(jí),* 如果是,則出棧符號(hào)棧頂元素,再出棧兩次數(shù)字棧元素,進(jìn)行運(yùn)算(最后出棧的數(shù)字放前面),運(yùn)算出來(lái)的結(jié)果放入數(shù)字棧,然后再5操作一次* 如果不是,符號(hào)直接入符號(hào)棧* 6.最后數(shù)字棧剩下最后一個(gè)數(shù)字,就是結(jié)果*/ public class StackCalculator {private Stack<Double> numList;private Stack<String> charList;public StackCalculator() {numList = new Stack<>();charList = new Stack<>();}public Double getPeek(ArrayList<String> cir) {for (int i = 0; i < cir.size(); i++) {String s = cir.get(i);if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")) {if (charList.isEmpty() || comparePriority(s) > comparePriority(charList.peek())) {charList.push(s);} else if (!charList.isEmpty() && comparePriority(s) <= comparePriority(charList.peek())) {while (!charList.isEmpty() && comparePriority(s) <= comparePriority(charList.peek())) {opera();}charList.push(s);}} else {numList.push(Double.parseDouble(s));}}while (numList.size() > 1) {opera();}Double peek = numList.peek();System.out.println(peek + "結(jié)果");return peek;}public void opera() {Double second = numList.pop();Double first = numList.pop();String pop = charList.pop();double answer = getSingleAnswer(first, second, pop);numList.push(answer);}public int comparePriority(String opera) {int por = 0;if (opera.equals("+")) {por = 0;}if (opera.equals("-")) {por = 0;}if (opera.equals("*")) {System.out.println("*****");por = 1;}if (opera.equals("/")) {por = 1;}return por;}public double getSingleAnswer(double a, double b, String c) {double answer = 0;if (c.equals("+")) {answer = a + b;} else if (c.equals("-")) {answer = a - b;} else if (c.equals("*")) {answer = a * b;} else if (c.equals("/")) {answer = a / b;}return answer;}}總結(jié)
以上是生活随笔為你收集整理的简单的计算器程序却蕴涵的有趣的数据结构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        