算術表達式

     這幾天學習《算法》這本書,第一章後面的習題,關於算術表達式,前序表達式,中序表達式,後序表達式的實現,我學習了兩天,不斷的編寫調試,初步實現了具體功能。首先

中序表達式((1+2)*((3-4)*(5-6))))
後序表達式12+34-56-**
前序表達式*+12*-34-56

     中序表達式是我們人類習慣使用的表達,但是,計算機很難使用。計算機一般是採用棧的技術來實現的,要麼轉換爲前序表達式,要麼轉換爲後序表達式。

     例如以後序表達式爲例,12+34-56-**

     首先2與1+等於3,變成334-56-**

     然後4-3變成,3156-**

      然後6-5變成,311**

   然後1*1,變成31*

    最後等於3

  從右至左取數,直到取出一個運算符,將剛取出的緊挨着運算符的兩個操作數按運算符進行計算,結果回填至運算符。重複該步驟,直到最後只剩下一個字符串則剩下的字符串即爲結果。
  後序表達式的字符串掃描方式正好和前序相反,是從左往右掃描,規則類似。

中序表達式轉後序表達式步驟

1、輸入字符串,如“2*3/(2-1)+3*(4-1)”

2、從字符串中取出下一個字符

  2.1.如果是操作數,則直接輸出

  2.2.如果是“(”,壓入棧中

  2.3.如果是運算符但不是“(”,“)”,則不斷循環進行以下處理

    2.3.1.如果棧爲空,則此運算符進棧,結束此步驟

    2.3.2.如果棧頂是“(”,則此運算符進棧,結束此步驟

    2.3.2.如果此運算符與棧頂優先級相同或者更高,此運算符進棧,結束此步驟

    2.3.4.否則,運算符連續出棧,直到滿足上述三個條件之一,然後此運算符進棧

  2.4、如果是“)”,則運算符連續出棧,直到遇見“(”爲止,將“(”出棧且丟棄之

3、如果還有更多的字符串,則轉到第2步

4、不在有未處理的字符串了,輸出棧中剩餘元素

程序源碼爲:

     
package sanzhang;
import ref.Stack;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class exe6 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //String strold="2*3/(2-1)+3*(4-1)";
        String strold="((1+2)*((3-4)*(5-6)))";
        //String strold="(1+2)+(8/4)";
        //String strold="3*(2-1)*3*(6/3)";
        //存放棧
        Stack<String> oper=new Stack<String>();
         //轉換成字符型數組
        char ch[]=strold.trim().toCharArray();
        //定義一個字符串數組
        String str[]=new String[ch.length];
        //存放結果數組
        List<String> list=new ArrayList<String>();
        //將原來表達式字符數組轉換成字符串數組
         for(int i=0;i<ch.length;i++)
        {
            str[i]=String.valueOf(ch[i]);
        }
         //逐個判斷字符串
        for(int i=0;i<str.length;i++)
        {
            //當輸入的是操作數時,直接添加到結果表達式後
            if(str[i].matches("^[1-9]\\d*$"))//正則表達式
            {
                list.add(str[i]);
            }
            else
                //當輸入的是左括號的時候,直接入棧
              if(str[i].equals("("))
              {
                  oper.push(str[i]);
              }
            //如果是右括號,則運算符連續出棧,直到遇見左括號爲止,左括號出棧且丟棄它
              else
              if(str[i].equals(")"))
                {
                                 
                       while(oper.size()> 0 && !oper.peek().equals("("))
                       {
                           //運算符連續出棧
                           String ss = oper.pop();                     
                           list.add(ss);
                       }
                       //直到遇到左括號,並丟棄之
                       oper.pop();
                                            
                }
            //如果爲操作符+-*/等
              else
              {
                  //如果棧爲空,直接進棧
                  if(oper.isEmpty())
                  {
                      oper.push(str[i]);
                      continue;
                  }
                  else
                      //如果棧頂爲左括號,運算符進棧
                  if(oper.peek().equals("("))
                  {
                      oper.push(str[i]);
                      continue;
                  }
                  else
                    //如果此運算符與棧頂優先級相同或更高,此運算符進棧,結束此步驟,取下一個字符,
                  if(priority(str[i])>priority(oper.peek()))
                  {
                                
                      oper.push(str[i]);
                  }
                  //如果三個條件均不滿足,則連續出棧,直到滿足其中三個一個,再進棧
                  else
                  {
                      do
                      {
                              
                          list.add(oper.pop());
                      }
                      while(!(oper.isEmpty()||oper.peek().equals("(")||priority(str[i])>priority(oper.peek())));
                      oper.push(str[i]);
                  }
              }
        }
        //如果此時棧非空,全部輸出
        while(!oper.isEmpty())
        {
                
            list.add(oper.pop());
        }
        //對結果動態數組遍歷
         for(int i=0;i<list.size();i++)
         {
             System.out.print(list.get(i)+"");
         }
         System.out.println();
         //輸出計算結果
         System.out.println(calcauteAfterExpression(list));
    }
    // 返回運算符的優先級
        public static int priority(String temp)
        {
            char ch=temp.charAt(0);
            int pri;
            switch (ch)
            {
            case '+':
                pri = 1;
                break;
            case '-':
                pri = 1;
                break;
            case '*':
                pri = 2;
                break;
            case '/':
                pri = 2;
                break;
            default:
                pri = 0;
            break;
            }
            return pri;
        }
        //判斷是否爲運算符
        public static boolean IsOperator(String temp)
        {
                      
            if(temp.equals("+")||temp.equals("-")||temp.equals("*")||temp.equals("/"))
                return true;
            return false;
        }
          /// <summary>
        /// 計算後序表達式
        /// </summary>
        //將操作數動態數組作爲參數進行傳遞
        public static int  calcauteAfterExpression(List<String> newExpression )
        {
           int result=0 ;
           if (newExpression.size() > 1)
            {
                int i = 0;
                for (i = 0; i < newExpression.size(); i++)
                {
                    //首先判斷是否爲運算符
                    if (IsOperator(newExpression.get(i)))
                    {
                        //取運算符左邊與運算符次左邊的進行運算
                        if (newExpression.get(i).equals("+"))
                        {
                            result =Integer.parseInt(newExpression.get(i-2))+Integer.parseInt(newExpression.get(i-1));
                        }
                        else if (newExpression.get(i).equals("-"))
                        {
                            result =Integer.parseInt(newExpression.get(i-2))-Integer.parseInt(newExpression.get(i-1));
                        }
                        else if (newExpression.get(i).equals("*"))
                        {
                            result =Integer.parseInt(newExpression.get(i-2))*Integer.parseInt(newExpression.get(i-1));
                        }
                        else if (newExpression.get(i).equals("/"))
                        {
                            result =Integer.parseInt(newExpression.get(i-2))/Integer.parseInt(newExpression.get(i-1));
                        }
                        break;
                    }
                }
                //第一輪計算完畢,將運算符所在的位置用計算得到的結果進行替換,並把運算符左邊的元素和次左邊的元素移除
                newExpression.set(i, String.valueOf(result));
                newExpression.remove(i-1);
                newExpression.remove(i-2);
                //再進行遞歸運算
                calcauteAfterExpression(newExpression);
            }
           //直到運算符全部用完,只剩下最後一個操作數,即爲我們所需要的值
          return Integer.parseInt(newExpression.get(0));
        }
}

中序表達式轉前序表達式步驟

1、反轉輸入字符串,如“2*3/(2-1)+3*(4-1)” 反轉後爲“ )1-4(*3+)1-2(/3*2”,

2、從字符串中取出下一個字符

  2.1.如果是操作數,則直接輸出

  2.2.如果是“)”,壓入棧中

  2.3.如果是運算符但不是“(”,“)”,則不斷循環進行以下處理

    2.3.1.如果棧爲空,則此運算符進棧,結束此步驟

    2.3.2.如果棧頂是“)”,則此運算符進棧,結束此步驟

    2.3.2.如果此運算符與棧頂優先級相同或者更高,此運算符進棧,結束此步驟

    2.3.4.否則,運算符連續出棧,直到滿足上述三個條件之一,然後此運算符進棧

  2.4、如果是“(”,則運算符連續出棧,直到遇見“)”爲止,將“)”出棧且丟棄之

3、如果還有更多的字符串,則轉到第2步

4、不在有未處理的字符串了,輸出棧中剩餘元素

5、再次反轉字符串得到最終結果

package sanzhang;
import java.util.*;
public class exe7 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //String strold="2*3/(2-1)+3*(4-1)";
        String strold="((1+2)*((3-4)*(5-6)))";
        Stack<String> oper=new Stack<String>();
        StringBuffer sb=new StringBuffer();//記錄結果表達式
        char ch[]=strold.trim().toCharArray();
        String str[]=new String[ch.length];
        List<String> list=new ArrayList<String>();
             
        for(int i=ch.length-1;i>=0;i--)
        {  
                list.add(String.valueOf(ch[i]));
        }
        //獲得反轉字符串
        for(int j=0;j<str.length;j++)
        {
            str[j]=list.get(j);
        }
              
        for(int i=0;i<str.length;i++)
        {
             //如果是操作數,直接輸出
            if(str[i].matches("^[1-9]\\d*$"))
            {
                sb.append(str[i]);
            }
            //如果是“)”,壓入棧中
            else
            if(str[i].equals(")"))
                    {
                       oper.push(str[i]);
                    }
            //如果是左括號,則運算符連續出棧,直到遇見右括號爲止,右括號出棧且丟棄它
            else
            if(str[i].equals("("))
            {
                //右括號
                while (oper.size()> 0 && !oper.peek().equals(")"))
                {
                    String ss = oper.pop();                         
                    sb.append(ss);
                }
                //右括號出棧且丟棄它
               oper.pop();
            }
            else
            {
                 //如果棧爲空,次運算符進棧,結束此步驟,取下一個字符
                if (oper.size()== 0)
                {
                         
                    oper.push(str[i]);
                }
                //如果棧頂是“)”,此運算符進棧,結束次步驟,讀取下一個字符
                else if (oper.peek().toString() == ")")
                {
                    oper.push(str[i]);
                }
                //如果此運算符與棧頂優先級相同或更高,此運算符進棧,結束次步驟,取下一個字符,
                else if (priority(str[i])>=priority(oper.peek().toString()))
                {
                    oper.push(str[i]);
                        
                }
                //否則,運算符連續出棧,直至滿足上述三個條件之一退出此步驟
                else
                {
                    do
                    {
                        String podstr = oper.pop().toString();                          
                        sb.append(podstr);
                    } while (!(oper.size() == 0 ||oper.peek().toString() == ")" ||
                        priority(str[i])>=priority(oper.peek().toString())));
                  oper.push(str[i]);
                         
                }
            }
                      
        }
            while(oper.size()!=0)
            {
                sb.append(oper.pop());
            }
                  
            System.out.println(sb.reverse());
    }
    // 返回運算符的優先級
    public static int priority(String temp)
    {
        char ch=temp.charAt(0);
        int pri;
        switch (ch)
        {
        case '+':
            pri = 1;
            break;
        case '-':
            pri = 1;
            break;
        case '*':
            pri = 2;
            break;
        case '/':
            pri = 2;
            break;
        default:
            pri = 0;
        break;
        }
        return pri;
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章