正在奮鬥天津大學的文兄前兩天在做演算法的時候遇到了一道棘手的題目。
當然,以文兄的聰明才智都不好解決的,我看著也一臉懵逼。然而有萬能的度娘,最後還是找到了解決方案。然而說的不是很詳細,這裡給出我和文兄對這道題的一點理解。
按照我的思路,應該先把算術表示式轉換成字尾表示式,
那麼(a+b)乘(c+d) 轉換成字尾表示式為 ab + cd + 乘(星號markdown出不來)
用棧儲存運算子,用佇列儲存數—–然後看過htdp
都知道,lisp就是這麼編譯計算的,按照計算機順序計算的特點很簡單就生成二叉樹。
然後,這明顯不符合題意,其中構造二叉樹子函式必須是遞迴函式。
而且,這明顯是道演算法題,和這些應該沒什麼關係。
我們的想法是既然括號裡面的先算,那麼最後的運算子肯定不在括號裡面。
然後找括號外的符號,因為乘除是要先算的,那麼最後的符號如果有加減的話,那就一定是加減。然後最後的符號作為根節點。
但是,我們都不知道在哪劃分左子樹和右子樹,以及怎樣尋找最後的
經過不懈的努力(努力搜),終於找到了遞迴的方法。
演算法思想是一致的,對於表示式,找到最後乙個被使用的運算子作為劃分,以此運算子為界,遞迴計算左邊的值,遞迴計算右邊的值,然後以此運算子進行運算,即可得到結果.
對於算術表示式,肯定先算括號裡的, 然後算乘除法,最後才算加減法 .
所以,先考慮加減法法,再考慮乘除法. 括號外的算術運算子可能很多,所以確定乙個原則,找整個算式中最右邊算術符號.
#include
#define maxsize 1000
using
namespace
std;
//二叉樹結點結構體定義
typedef
struct btreenodebtreenode;
//算術表示式轉化二叉樹
/* afa為指向表示式字串的指標
s為要轉化的表示式字串的起始位置
e為要轉化的表示式字串的結束位置的後乙個
*/
btreenode* afatobtree(char *afa,int s,int e)
/* local_r記錄當前要轉化的表示式生成二叉樹的根節點操作符的位置
flag記錄是否當前搜尋在括號裡面
m_m_p記錄當前表示式中括號外面最右邊的+、-位置
a_s_p記錄當前表示式中括號外面最右邊的*、/位置
*/int local_r=0,flag=0;
int m_m_p=0,a_s_p=0;
for(int i=s;iif(afa[i]=='(')flag++;
else
if(afa[i]==')')flag--;
if(flag==0)
} if((m_m_p==0)&&(a_s_p==0))
//如果式子整個有括號如(a-b*c+d),即括號外面沒有操作符,則去掉括號找二叉樹
afatobtree(afa,s+1,e-1);
else
} void main()
由於要找的是括號外的算術運算子, 所以得想辦法避免記錄括號內的運算子,所以設定了乙個標誌,初始為零,一旦遇到乙個左括號, +1, 這時候說明目前在括號內,不應該記錄運算子, 當遇到右括號,-1,標誌恢復為0,這時候說明目前已經走出括號,可以記錄運算子 .
掃瞄完整個表示式的時候,m_m_p記錄了最右邊的括號外的+-號,a_s_p記錄了最右邊的括號外的*/號.
把(m_m_p==0)&&(a_s_p==0),說明整個算式被括號包圍起來了.
括號外面沒有操作符,所以可以遞迴運算時忽略這對括號。
最後,祝文兄考個好成績!
演算法中的算術表示式
1 2 3 4 5 我們如何通過演算法來計算上面的表示式呢?方法 用2個棧 乙個用於儲存運算子,乙個用於儲存運算元 其中的運算子包括 表示式有括號 運算子 和運算元 數字 組成。我們根據以下4種情況從左到右逐個將這些實體送入棧處理 將運算元壓入運算元棧 將運算子壓入運算子棧 忽略左括號 在遇到右括號...
演算法學習 算術表示式
題目描述 implement a basic calculator to evaluate a expression string.the expression string may contain open and closing parentheses the plus or minus sig...
算術表示式的轉換
小明在學習了資料結構之後,突然想起了以前沒有解決的算術表示式轉化成字尾式的問題,今天他想解決一下。因為有了資料結構的基礎小明很快就解出了這個問題,但是他突然想到怎麼求出算術表示式的字首式和中綴式呢?小明很困惑。聰明的你幫他解決吧。輸入 輸入一算術表示式,以 字元作為結束標誌。資料保證無空格,只有一組...