此題是NYOJ第257題。
剛開始我還沒怎麼考慮括號的情況,但後來邊寫邊想就想明白了。我的算法是:
1.如果開始的字符是單個數字,並且後面不存在操作符。那麼直接生成結點並賦值。否則跳到步驟3。
2.如果開始遇到左括號,且最後一個字符是右括號。除去括號,繼續遞歸生成二叉樹。否則那麼繼續步驟3。
3.找到最右邊優先級最低的操作符。生成一個結點,並且將符號放入數據區。括號內的整體當作一個數來看暫時不管。
4.然後分別將左右兩邊的串,分別遞歸的計算。
這是很典型的分治算法了。其要點就兩點:
1.找到優先級最低且在最右的操作符。
2.將左右兩邊式子看作子樹,遞歸運算得出結果。
開始的時候沒有考慮到多重括號的情況RE了幾次。然後自己是試着寫了個嵌套很多個的式子,問題就暴露出來了。以後還是得多想想可能的陷阱數據後再寫代碼吧。
代碼如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct asd
{ int a;
int flag;
struct asd * left;
struct asd *right;
}node;
void translate(char s[],int length,node **head)
{
int i;
int flag=0;
int max;
int kuohao;
if(s[0]>='0'&&s[0]<='9')
{
for(i=0;i<length;i++)//如果需要遞歸計算子式
if(!(s[i]>='0'&&s[i]<='9'))
break;
if(i==length)//如果只是一個數字
{ *head=(node*)malloc(sizeof(node));
(*head)->a=atoi(s);
(*head)->flag=1;
(*head)->left=NULL;
(*head)->right=NULL;
return ;
}
}
if(s[0]=='('&&s[length-1]==')')//當式子只有一個整體的括號的時候
{
translate(&s[1],length-2,head);
return;
}
for(i=length-1,flag=0;i>=0;i--)//找符號位置
{
if(s[i]=='+'||s[i]=='-')//找到最合適的符號。
{
max=i;
break;
}
else if(flag==0&&(s[i]=='/'||s[i]=='*'||s[i]=='('))//
{ max=i;
flag=1;//用於標識只存在*/的式子
}
else if(s[i]=='/'||s[i]=='*'||s[i]=='(')
continue;
else if(s[i]==')')
{ kuohao=1;
i--;
while(kuohao!=0)//爲了保證多重括號嵌套的情況,簡單的模擬了一個括號匹配的過程
{ if(s[i]==')')
kuohao++;
if(s[i]=='(')
kuohao--;
i--;
}
i++;
}
}
*head=(node *)malloc(sizeof(node));//寫入符號
(*head)->a=s[max];
(*head)->flag=0;
translate(s,max,&((*head)->left));//遞歸計算左子樹
translate(&s[max+1],length-max-1,&((*head)->right));//遞歸計算右子樹
}
void houxu(node *head)//後序遍歷整棵樹
{ if(head==NULL)
return;
houxu(head->left);
houxu(head->right);
if(head->flag==1)
printf("%d",head->a);
else
printf("%c",head->a);
}
int main()
{
int t;
char get[1010];
node *head;
freopen("test.txt","r",stdin);
scanf("%d",&t);
while(t--)
{ scanf("%s",get);
translate(get,strlen(get),&head);
houxu(head);
printf("\n");
}
}