《算法》第一章——Dijkstra雙棧表達式求值

思路:

使用兩個棧分別保存運算符和操作數。將表達式從左到右依次送人棧中處理:

  1. 將操作數壓人操作數棧。
  2. 將運算符壓人運算符棧。
  3. 忽略左括號。
  4. 若遇到右括號,則彈出一個運算符,並彈出所需的操作數,並將這部分表達式的運算結果求出後壓人操作數棧。
  5. 處理完所有右括號後,操作數棧中的最後一個指就是表達式的值。

代碼:

#include<iostream>
#include<sstream>
#include<string>
#include<stack>
using namespace std;

template<typename T>
T strToNum(const string& str)
{
  istringstream istr(str);
  T num;

  istr >> num;
  return num;
}

int main(void)
{
  string exp;
  stack<double> vals;//operand stack
  stack<string> ops;//operator stack

  while(cin >> exp,!cin.eof())//"ctrl+z" for console EOF
  {
    if(cin.bad())
    {
      cerr << "error:IO stream corrupt " << endl;
    }
    if(cin.fail())
    {
      cerr << "bad data!try again!" << endl;
      cin.clear();
      cin.sync();
      continue;
    }
  //  cout << exp <<endl;
    if(string("+") == exp)
    {
      ops.push(exp);
    }
    else if(string("-") == exp)
    {
      ops.push(exp);
    }
    else if(string("*") == exp)
    {
      ops.push(exp);
    }
    else if(string("/") == exp)
    {
      ops.push(exp);
    }
    else if(string("(") == exp)
    {}
    else if(string(")") == exp)
    {
      double val = vals.top();
      vals.pop();
      string op = ops.top();
      ops.pop();

      if(string("+") == op)
      {
        val = vals.top() + val;
        vals.pop();
      }
      else if(string("-") == op)
      {
        val = vals.top() - val;
        vals.pop();
      }
      else if(string("*") == op)
      {
        val = vals.top() * val;
        vals.pop();
      }
      else if(string("/") == op)
      {
        val = vals.top() / val;
        vals.pop();
      }
      vals.push(val);
    }
    else
    {
      //method 1:
      //double operand = strToNum<double>(exp);
      //method 2:
      double operand = stod(exp);//cast string to num.c++11
      cout << operand <<endl;
      vals.push(operand);
    }
  }

  cout << "ret-->" <<vals.top();
  getchar();
  return 0;
}


代碼只考慮了每個操作符構成的表達式都用括號括起來的情況。


心得體會:

c++的stack適配器的pop函數只是執行出棧操作並不返回棧頂元素。top函數是返回棧頂元素。


題目:

編寫一段程序,從標準輸入得到一個缺少左括號的表達式並打印出補全括號之後的中綴表達式。(這裏也只考慮每個操作符構成的表達式都用括號括起來的情況)

思路:

借鑑上面的思路。上面是在操作符和對應操作數出棧後計算出它們的值後再壓人操作數棧,這裏爲了還原表達式所以不需要計算出表達式的值,而是應該將整個表達式(包括左右括號)壓人操作數棧。

代碼:

#include<iostream>
#include<sstream>
#include<string>
#include<stack>
using namespace std;

int main(void)
{
  string exp;
  stack<string> vals;//operand stack
  stack<string> ops;//operator stack

  while(cin >> exp,!cin.eof())//"ctrl+z" for console EOF
  {
    if(cin.bad())
    {
      cerr << "error:IO stream corrupt " << endl;
    }
    if(cin.fail())
    {
      cerr << "bad data!try again!" << endl;
      cin.clear();
      cin.sync();
      continue;
    }
  //  cout << exp <<endl;
    if(string("+") == exp)
    {
      ops.push(exp);
    }
    else if(string("-") == exp)
    {
      ops.push(exp);
    }
    else if(string("*") == exp)
    {
      ops.push(exp);
    }
    else if(string("/") == exp)
    {
      ops.push(exp);
    }
    else if(string("(") == exp)
    {}
    else if(string(")") == exp)
    {
      string val = vals.top();
      vals.pop();
      string op = ops.top();
      ops.pop();

      if(string("+") == op)
      {
        val = string("(")+vals.top() +string("+")+ val+string(")");
        vals.pop();
      }
      else if(string("-") == op)
      {
        val = string("(")+vals.top() +string("-")+ val+string(")");
        vals.pop();
      }
      else if(string("*") == op)
      {
        val = string("(")+vals.top() +string("*")+ val+string(")");
        vals.pop();
      }
      else if(string("/") == op)
      {
        val = string("(")+vals.top() +string("/")+ val+string(")");
        vals.pop();
      }
      vals.push(val);
    }
    else
    {
      vals.push(exp);
    }
  }

  cout << "ret-->" <<vals.top();
  getchar();
  return 0;
}


參考:http://blog.csdn.net/k346k346/article/details/50927002----C++數值類型與string的相互轉換

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