去除運算式裡面多餘的()

來源:互聯網
上載者:User

鍵盤輸入一個含有括弧的四則運算運算式,可能含有多餘的括弧,編程整理該運算式,
去掉所有多餘的括弧,原運算式中所有變數和運算子相對位置保持不變,並保持與原運算式
等價。
  例:輸入運算式       應輸出運算式
    a+(b+c) a+b+c
(a*b)+c/d a*b+c/d
a+b/(c-d) a+b/(c-d)
 注意輸入a+b時不能輸出b+a。
  運算式以字串輸入,長度不超過255。輸入不要判錯。
  所有變數為單個小寫字母。只是要求去掉所有多餘括弧,不要求對錶達式化簡。

             二、演算法分析

  四則運算運算式含運算子'+','-','*','/','(',')',其優先順序由低至高為
      '+','-' ─→ '*','/' ─→ '(',')'
  一個括弧是否作為多餘的括弧剔除,關鍵是分析該括弧內優先順序最低的運算子與左鄰括
號或右鄰括弧的運算子之間的運算優先關係:
  設待整理的運算式為(s1 op s2);
op—括弧內優先順序最低的運算子('+','-'或'*','/');

  1、若左鄰括弧的運算子為'/',則無論op為何運算子,括弧必須保留,即…… /( s1
op s2)……。因為原式(s1 op s2)作為除數,一旦去除括弧後,僅s1作為除數,不
可能與原式等價;
  2、若左鄰括弧的運算子為'*'或'-',而op為'+'或'-',則保留括弧,即……*-(s1+-
s2)。不能去除括弧的原因是:
若左鄰標符為'*',優先順序大於括弧內運算子,因此必須用括弧保證括弧內的'+'或
'-'優先進行;
若左鄰算符為'-',去除括弧後,由於括弧內的'+'、'-'要變號, 結果不與原式等
價;
  3、若右鄰括弧的運算子為'*'或'/',而op為'+'或'-',原式中的op運算必須優先進行,
因此括弧不能去除,即(s1+-s2)*/……;
  4、除上述情況外,括弧去除,結果與原式等價,即 …s1 op s2…。
  我們從最裡層嵌套的括弧開始,依據上述規律逐步向外層進行括弧整理,直至最外層的
括弧保留或去除為止。這個整理過程可以用下述的一個遞迴過程reduce描述:
  function reduce(運算式串s,var op):string;
{ 整理運算式s,並返回s串中優先順序最低的運算子op和整理結果 }
begin
if s是變數 then
begin
op=' '; reduce=變數s; exit
end;
if s是(s')形式 then
begin
reduce=reduce(s',op); exit
end;
{ s是's1 op s2' 形式 }
a=reduce(s1,c1);b=reduce(s2,c2);
if (op in ['*','-']) and (c2 in ['+','-']) then s2='(s2)';
if (op in ['*','/']) and (c1 in ['+','-']) then s1='(s1)';
if (op in ['/']) and (c2<>' ') then s2='(s2)';
reduce='s1 op s2'
end;

例如,剔除運算式'((a+b)*f)-(i/j)'中多餘的括弧。依據上述演算法進行整理的過程如下:
  
'((a+b)*f)-(i/j)','-'
┌────────┴─────────┐
'((a+b)*f)','*' '(i/j)','/'
│ │
'(a+b)*f','*' 'i/j','/'
┌───┴────┐ ┌─┴──┐
'(a+b)','+' 'f',' ' 'i',' ' 'j',' '

'a+b','+'
┌┴────┐
'a',' ' 'b',' '
       (圖1.1-1)
最後,自底向上得整理結果:(a+b)*f-i/j。

 三、程式分析

Program P11;

var
ins : string; { 算術運算式 }
p : char; { 最低級運算子 }

function suitable(s:string;i:byte):byte;
{ s[i]為')',函數suitable輸出與之相對應的'('在s中的位置 }
var
t:byte;
begin
t:=1;
repeat
dec(i);
if s[i]=')'
then inc(t)
else if s[i]='(' then dec(t)
until t=0;
suitable:=i
end; {suitable}

function find(s:string):byte;
{ 輸出運算式s中最低級算符的位置 }
var
i,k:byte;
begin
i:=length(s);k:=0;
while i>0 do
begin
if (s[i]='+') or (s[i]='-')
then begin
find:=i;exit
end; {then}
if (k=0) and ((s[i]='*') or (s[i]='/')) then k:=i;
if s[i]=')' then i:=suitable(s,i);
dec(i)
end; {while}
find:=k
end; {find}

function reduce(s:string;var p:char):string;
{ 整理運算式s並返回優先順序最低的運算子p }
var
a,b:string; { 運算式s的左項和右項整理的結果 }
c1,c2:char; { 運算式s的左項和右項的最低級運算子 }
i:byte; { 運算式s的最低級運算子的位置 }
begin
if length(s)=1 { 若運算式是變數則返回變數 }
then begin
reduce:=s;p:=' ';exit
end; {then}
if (s[length(s)]=')') and (suitable(s,length(s))=1)
{ 若運算式被一對括弧包住,則返回括弧內運算式的整理結果 }
then begin
reduce:=reduce(copy(s,2,length(s)-2),p);
exit
end; {then}
i:=find(s);p:=s[i]; { 找出最低級運算子及其位置 }
a:=reduce(copy(s,1,i-1),c1); { 分別整理左項和右項 }
b:=reduce(copy(s,i+1,length(s)-i),c2);
{ 根據p和c1,c2,決定是否加括弧 }
if (p in ['*','-']) and (c2 in ['+','-']) then b:='('+b+')';
if (p in ['*','-']) and (c1 in ['+','-']) then a:='('+a+')';
if (p='/') and (c2<>' ') then b:='('+b+')';
reduce:=a+p+b { 返回整理結果 }
end; {reduce}

begin
write('Str = ');
readln(ins); { 輸入算術運算式 }
writeln(reduce(ins,p)) { 剔除多餘括弧並列印整理結果 }
end. {main}

 

//////////////////////////////////////////////////////////////////////////////////////////////////////

 

例23 剔除多佘的括弧。

鍵盤輸入一個含有括弧的四則運算運算式,可能含有多佘的括弧,編程整理該運算式,去掉所有多佘的括弧,原運算式中所有變數和運算子相對位置保持不變,並保持與原運算式等價。

例如:

輸入運算式

應輸出運算式

A+b(+c)

A+b+c

(a*b)+c/(d*c)

A*b+a/(d*c)

A+b/(c-d)

A+b/(c-d)

注意輸入工A+b時不能輸出B+a。

運算式以字串輸入,長度不超過255,輸入不需要判錯。

所有變數為單個小寫字母。只是要求去掉所有多佘括弧,不要求對錶達式簡化。

演算法分析

對於四則運算運算式,我們分析一下哪些括弧可以去掉。

設待整理的運算式為(s1 op s2);op為括弧內優先順序最低的運算子(“+”,“-”或“×”,“/”);

①左鄰括弧的運算子為“/”,則括弧必須保留,既…/(s1 op s2)…形式。

②左鄰括弧的預算符為“*”或“-”。而op為“+”或“-”,則保留括弧,既…×(s1+s2)…”、“…-(s1+s2)…”、“…×(s1-s2)…”、“…-(s1-s2)…”。

③右鄰括弧的運算子為“×”或“/”,而op 為“+”或“-”,原式中的op運算必須優先進行,因此括弧不去除,即“(s1+s2)*…”。

除上述情況外,可以把括弧去除,即“…s1 op s2…”等價於“…(s1 op s2)…”。

人們從最裡層嵌套的括弧開始,依據上述規律逐步向外進行括弧整理,直至最外層括弧保留或去除為止。這個整理過程可以用一個遞迴的過程來實現。 

 

 

 

 

 

 

 

 

【參考程式】

program aa;

 var ch:char;

    st:string;

 function loc(s:string;i:byte):byte;

 var q:byte;

 begin

    q:=1;

    repeat

      inc(i);

      if s[i]='(' then inc(q)

      else if s[i]=')' then dec(q);

    until q=0;

    loc:=i;

 end;

 function find(s:string):byte;

 var i,k:byte;

 begin

    i:=1;

    k:=0;

    while i<=length(s) do

     begin

       if (s[i]='+')or(s[i]='-') then

        begin

          find:=i; exit;

        end;

      if(k=0)and((s[i]='*')or(s[i]='/')) then k:=i;

       if s[i]='(' then i:=loc(s,i);

       inc(i);

     end;

    find:=k;

 end;

 function del(s:string;var p:char):string;

 var i,j:byte;

      ch1,ch2:char;

      left,right:string;

 begin

    i:=0; j:=0;

    i:=pos('(',s); j:=pos(')',s);

    if (i=0)and(j=0) then

      begin del:=s; exit; end;

    if (s[1]='(')and(loc(s,1)=length(s)) then

     begin

       del:=del(copy(s,2,length(s)-2),p);

       exit;

     end;

    i:=find(s);

    p:=s[i];

    left:=del(copy(s,1,i-1),ch1);

    right:=del(copy(s,i+1,length(s)-i),ch2);

    if (p in ['*','/'])and(ch1 in ['+','-']) then

      left:='('+left+')';

    if (p in ['*','/'])and(ch2 in ['+','-'])or(p='/')and(ch2 <>' ') then

      right:='('+right+')';

    del:=left+p+right;

 end;

 begin

    readln(st);

    writeln(del(st,ch));

 end.

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.