hdu 1123 Complicated Expressions 重点后缀表达式转中缀表达式

该博客主要介绍了如何将中缀表达式转换为后缀表达式,以及从后缀表达式转换回中缀表达式,目标是去除不必要的括号。中缀转后缀通过栈实现,根据运算符优先级判断入栈或出栈;后缀转中缀同样使用栈,处理复合表达式的优先级来决定是否添加括号。

这道题是去除多余的括号。
思路是: 首先中缀表达是转后缀表达式。 这样得出的字符串是完全不包含括号的。
再把后缀表达式转变成中缀表达式,这时只要求加上必要的括号,这样就能保证括号最少。

中缀转后缀

对于中缀转后缀,一个栈 op 来存放运算符,括号。

对于字符串s 从头开始扫描,
遇见操作数直接输出到另一个字符串t,用来存放转化后的后缀表达式。
遇见操作符,首先定义优先级 * / 优先级2 ,大于 优先级为 1的 + -, ( 左括号具有最高优先级 3
如果op 为空,或者 当前栈顶元素为 '('则直接把当前处理字符(操作符) 入栈。或者当前栈顶操作符优先级小于 要处理的字符所代表的优先级也入栈。

如果当前栈顶元素小于或等于(不大于) 当前处理字符(操作符)的优先级。 则出栈并追加到t的末尾,直到栈顶元素优先级小于当前处理字符优先级,或者栈为空
然后再把当前处理字符入栈。

如果当前处理字符是 则把栈顶元素出栈追加到 t末尾 ,直到遇见 ,( 不追加。

处理完字符串s
最后把栈中所有元素追加到t 。 t就是后缀表达式。

详细参考博客: http://blog.youkuaiyun.com/sgbfblog/article/details/8001651

代码:

int priority(char c){

    if(c=='+'||c=='-') return 1;
    else if(c=='*'||c=='/') return 2;
    else if(c=='(') return 3;
}

string middle2Back(string s){

    string t;
    t="";
     char tmp;
    stack<char> op;

    int n=s.length();

    for(int i=0;i<n;i++){

        // if is the num then output
        if(s[i]>='a'&&s[i]<='z'){
                t+=s[i];

        }else if(s[i]=='('){   // if is ( then push stack op

            op.push(s[i]);
        }else if(s[i]==')'){ //  if is ) then output op until meet ( but do not output ( just pop (


            while(!op.empty()){
                tmp=op.top();
                if(tmp=='('){

                    op.pop();
                    break;
                }
                t+=tmp;
                op.pop();
            }
        }
        else {

            // else
            while(!op.empty()){

                tmp=op.top();

                int p1=priority(tmp);

                int p2=priority(s[i]);

                 // if s[i] 's priority greater than top of stack op then push s[i] or s[i] is (

                if(p2>p1||tmp=='(') break;

                // else  output the stack op unitl meet a greater or (
                t+=tmp;
                op.pop();

            }

            op.push(s[i]);
        }
    }

    // add the remain of stack op
    while(!op.empty()){

        t+=op.top();
        op.pop();
    }
    return t;
}
后缀转中缀

对于后缀如何转中缀呢?
首先同样定义优先级,, 对于后缀表达式, 定于操作数拥有最高优先级 3, * ,/ 优先级为2 +,- 优先级为1,
同样需要一个栈 stack 来存放结果 。
随着处理会得到一些复合表达式,同样的这些复合表达式也应有优先级,复合表达式的优先级定义为 ,和最后一个运算的操作符的优先级相同。举例,如果一个符合表达式最后一个 + ,- 那么优先级和 +,-相同,同样也可能是和 *,/ 的优先级相同。
我们会把遇到操作符后每一步的结果都作为一个栈元素,入栈,所以需要定义一个结构体,为了方便我们进行操作。

struct Expre{
    string  exp;
    int p;  // priority 
}

从头扫描 后缀表达式字符串 t
对于操作数直接入栈,
对于操作符,对于
操作符 +:
从stack 出栈 2个元素,直接用+ 连接,并入栈,表达式优先级和+号相同。
对于操作符 -
从栈顶出栈两个元素, 最先出栈的那个 加上括号(),并和第二个出栈的元素用 - 拼接 后重新入栈。 表达式优先级为 -
操作符 *:
从栈顶出栈两个元素,对于优先级小于*的表达式加上括号,并用* 拼接后重新入栈,表达式优先级同 *.
对于操作符/:
从栈顶出栈两个元素,最先出栈元素表达式的优先级小于或等于 /优先级时,加上括号。
第二个出栈的元素表达式优先级小于/的优先级时,加上括号,
并用 /拼接后入栈,
处理完子符串t后,输出栈顶元素表达式即得到,加上括号的后缀转中缀的表达式。
代码:

string back2Middle(string t){


    stack<Expre> st;

    string a="";
    string b="";

    string x;
    Expre tmp;

    Expre ta,tb;



    int n=t.length();

    int p1;
    for(int i=0;i<n;i++){



        if(t[i]>='a'&&t[i]<='z'){


            tmp.exp=t[i];

            tmp.p=3;
            st.push(tmp);

        }else if(t[i]=='+'){  //if op is + then just concate

            b=st.top().exp;
            st.pop();
            a=st.top().exp;
            st.pop();

            tmp.exp=a+'+'+b;

            tmp.p=1;
            st.push(tmp);

        }else if(t[i]=='-'){

            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('-');

            // + - is the smallest so, no one lower than p1
            // if the op is - then the second need add () if its priority <=  -
            if(tb.p<=p1){

                b='('+tb.exp+')';
            }else b=tb.exp;

            // no need charge because not less than -
            a=ta.exp;

            tmp.exp=a+'-'+b;

            tmp.p=1;

            st.push(tmp);

        }else if(t[i]=='*'){

            //only the priority less than *  need add ()
            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('*');
            if(tb.p<p1){
                b='('+tb.exp+')';
            }else b=tb.exp;

            if(ta.p<p1){
                a='('+ta.exp+')';
            }else a=ta.exp;

            tmp.exp=a+'*'+b;

            tmp.p=2;

            st.push(tmp);

        }else if(t[i]=='/'){
            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('*');
            // like -   if the op is / then the second less or equal p1 need add ()
            if(tb.p<=p1){
                b='('+tb.exp+')';
            }else b=tb.exp;
            //but the first is less need add (0
            if(ta.p<p1){
                a='('+ta.exp+')';
            }else a=ta.exp;

            tmp.exp=a+'/'+b;
            tmp.p=2;

            st.push(tmp);

        }

    }
    return st.top().exp;
}

AC 代码:

#include <iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<stack>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

struct Expre{

    string exp="";

    int p=0;
};


int priority(char c){

    if(c=='+'||c=='-') return 1;
    else if(c=='*'||c=='/') return 2;
    else if(c=='(') return 3;
}



string middle2Back(string s){

    string t;
    t="";
     char tmp;
    stack<char> op;

    int n=s.length();

    for(int i=0;i<n;i++){

        // if is the num then output
        if(s[i]>='a'&&s[i]<='z'){
                t+=s[i];

        }else if(s[i]=='('){   // if is ( then push stack op

            op.push(s[i]);
        }else if(s[i]==')'){ //  if is ) then output op until meet ( but do not output ( just pop (


            while(!op.empty()){
                tmp=op.top();
                if(tmp=='('){

                    op.pop();
                    break;
                }
                t+=tmp;
                op.pop();
            }
        }
        else {

            // else
            while(!op.empty()){

                tmp=op.top();

                int p1=priority(tmp);

                int p2=priority(s[i]);

                 // if s[i] 's priority greater than top of stack op then push s[i] or s[i] is (

                if(p2>p1||tmp=='(') break;

                // else  output the stack op unitl meet a greater or (
                t+=tmp;
                op.pop();

            }

            op.push(s[i]);
        }
    }

    // add the remain of stack op
    while(!op.empty()){

        t+=op.top();
        op.pop();
    }
    return t;
}

string back2Middle(string t){


    stack<Expre> st;

    string a="";
    string b="";

    string x;
    Expre tmp;

    Expre ta,tb;



    int n=t.length();

    int p1;
    for(int i=0;i<n;i++){



        if(t[i]>='a'&&t[i]<='z'){


            tmp.exp=t[i];

            tmp.p=3;
            st.push(tmp);

        }else if(t[i]=='+'){  //if op is + then just concate

            b=st.top().exp;
            st.pop();
            a=st.top().exp;
            st.pop();

            tmp.exp=a+'+'+b;

            tmp.p=1;
            st.push(tmp);

        }else if(t[i]=='-'){

            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('-');

            // + - is the smallest so, no one lower than p1
            // if the op is - then the second need add () if its priority <=  -
            if(tb.p<=p1){

                b='('+tb.exp+')';
            }else b=tb.exp;

            // no need charge because not less than -
            a=ta.exp;

            tmp.exp=a+'-'+b;

            tmp.p=1;

            st.push(tmp);

        }else if(t[i]=='*'){

            //only the priority less than *  need add ()
            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('*');
            if(tb.p<p1){
                b='('+tb.exp+')';
            }else b=tb.exp;

            if(ta.p<p1){
                a='('+ta.exp+')';
            }else a=ta.exp;

            tmp.exp=a+'*'+b;

            tmp.p=2;

            st.push(tmp);

        }else if(t[i]=='/'){
            tb=st.top();
            st.pop();
            ta=st.top();
            st.pop();
            p1=priority('*');
            // like -   if the op is / then the second less or equal p1 need add ()
            if(tb.p<=p1){
                b='('+tb.exp+')';
            }else b=tb.exp;
            //but the first is less need add (0
            if(ta.p<p1){
                a='('+ta.exp+')';
            }else a=ta.exp;

            tmp.exp=a+'/'+b;
            tmp.p=2;

            st.push(tmp);

        }

    }

    return st.top().exp;
}

int main()
{
    int n;
    scanf("%d",&n);
    string s;
    string t;
    string result;
    while(n--){
        cin>>s;

        t=middle2Back(s);
       result=back2Middle(t);
       cout<<result<<endl;
    }
    return 0;
}
在CUDA编程中,kernel<<<>>>是用来启动并行计算的语法。在<<<>>>中,必须指定一个表达式作为参数,该表达式指定了并行计算的线程块(block)和线程(thread)的数量。这个表达式的格式可以是一个常数,也可以是一个变量或者一个计算表达式。 例如,如果想要启动一个有16个线程块和256个线程的并行计算,可以使用以下形式的表达式: kernel<<<16, 256>>>(); 其中,16表示线程块的数量,256表示每个线程块中的线程数量。 另外,如果希望在编译时指定默认的线程块和线程数量,可以使用宏定义或者模板的方式来实现。通过设置默认值,并在调用kernel时不指定表达式,就可以使用默认的线程块和线程数量。同时,也可以添加依赖关系来根据不同的条件设置不同的默认值。 总结起来,当使用kernel<<<>>>时,必须提供一个表达式来指定线程块和线程的数量。这个表达式可以是一个常数、变量或者计算表达式。另外,也可以通过设置默认值和添加依赖关系来实现更灵活的使用方式。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [玩CUDA——提示应输入表达式](https://blog.youkuaiyun.com/gaohang_hdu/article/details/81119627)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Kconfig语法](https://download.youkuaiyun.com/download/pengfei24/4328218)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值