波兰式的各种表示及转化

中缀表达式转换为逆波兰表达式(后缀表达式)

首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:

(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈

(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。

(3)若取出的字符是“(”,则直接送入S1栈顶。

(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。

(5)重复上面的1~4步,直至处理完所有的输入字符

(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。

完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!

摘自百度百科

 

 1 typedef char SElemType_Char;
 2 typedef struct {
 3     SElemType_Char* base, * top;
 4     int listsize;
 5 }SqStack;//数据结构
 6 
 7 Status InitSqStack(SqStack* S) {
 8     (*S).base = (SElemType_Char*)malloc(STACK_INT_SIZE*sizeof(SElemType_Char));
 9     (*S).top = (*S).base;
10     (*S).listsize = STACK_INT_SIZE;
11     return OK;
12 }//初始化
13 
14 Status Push_SqStack(SqStack* S, SElemType_Char e) {
15     *((*S).top++) = e;
16     return OK;
17 }//入栈
18 
19 SElemType_Char Pop_SqStack(SqStack* S) {
20     return *--(*S).top;
21 }//出栈
22 
23 void Convert(char* S,SqStack *T1,SqStack T2) {
24     char* t = S, *p;
25     Push_SqStack(&T2, '#');
26     while (*t) {
27         switch (*t){
28         case'+':
29         case'-':
30             if (*(T2.top - 1) == '#'|| *(T2.top - 1) == '(') 
31                 Push_SqStack(&T2, *t);
32             else {
33                 do {
34                     Push_SqStack(T1, Pop_SqStack(&T2));
35                 } while (*(T2.top - 1) != '#');
36                 Push_SqStack(&T2, *t);
37             }
38             break;
39         case'*':
40         case'/':
41             if (*(T2.top - 1) == '+' || *(T2.top - 1) == '-' || *(T2.top - 1) == '#' || *(T2.top - 1) == '(')
42                 Push_SqStack(&T2, *t);
43             else {
44                 do {
45                     Push_SqStack(T1, Pop_SqStack(&T2));
46                 } while (*(T2.top - 1) == '+' || *(T2.top - 1) == '-' || *(T2.top - 1) == '#');
47                 Push_SqStack(&T2, *t);
48             }
49             break;
50         case')':
51             do {
52                 Push_SqStack(T1, Pop_SqStack(&T2));
53             } while (*(T2.top - 1) != '(');
54             Pop_SqStack(&T2);
55             break;
56         case'(':
57             Push_SqStack(&T2, *t);
58             break;
59         default:
60             Push_SqStack(T1, *t);
61             break;
62         }
63         t++;
64     }
65     while(T2.base!=T2.top-1)
66         Push_SqStack(T1, Pop_SqStack(&T2));
67     p = (*T1).base;
68     while (p != (*T1).top)
69         printf("%c", *p++);
70     printf("\n");
71 }//转化并输出
View Code

 

逆波兰式求解: 

如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。

 

 1 char Calculate(SqStack T1,SqStack T2) {
 2     char p, q;
 3     while (T1.base != T1.top)
 4         Push(&T2, Pop(&T1));
 5     while (T2.base != T2.top) {
 6         if (*(T2.top - 1) >= '0' && *(T2.top - 1) <= '9')
 7             Push(&T1, Pop(&T2));
 8         else {
 9             if (*(T2.top - 1) == '+')
10                 Push(&T1, (Pop(&T1) - '0') + (Pop(&T1) - '0')+'0');
11             else if (*(T2.top - 1) == '-') {
12                 p = Pop(&T1);
13                 q = Pop(&T1);
14                 Push(&T1, (q - '0') - (p - '0') + '0');
15             }
16             else if (*(T2.top - 1) == '*')
17                 Push(&T1, (Pop(&T1) - '0') * (Pop(&T1) - '0')+'0');
18             else if (*(T2.top - 1) == '/') {
19                 p = Pop(&T1);
20                 q = Pop(&T1);
21                 Push(&T1, (q - '0') / (p - '0') + '0');
22             }
23             Pop(&T2);
24         }
25     }
26     return *T1.base;
27 }
View Code

  

中缀表达式转前缀表达式:

①从右到左扫描中缀表达式

②遇到数字压入S2

③遇到操作符,与S1的栈顶比较

a.如果S1为空,或者栈顶是 ),直接入栈S1

b.否则,如果符号优先级比栈顶高或者相等,直接入栈S1

c.否则,S1顶出栈,压入S2。然后继续回到步骤a比较。

④遇到括号的时候

a. ) :直接压入S1

b. ( :依次把S1弹出,压入S2,直到遇上 )。括号可以丢弃

⑤重复上述扫描步骤,直到扫描完成

⑥S1中如果还有元素,全部弹出压入S2

⑦S2依次弹出得到前缀表达式
--------------------- 
参考 https://blog.csdn.net/weixin_39731083/article/details/81667043

Status Calculate(SqStack *S1,char *S3) {
    SqStack S2;
    InitSqStack(&S2);
    (*S1).top = (*S1).base;
    int i = strlen(S3) - 1;
    while (i >= 0) {
        switch (S3[i]){
        case'+':
        case'-':
        case'*':
        case'/':
            do {
                if (S2.base == S2.top || *(S2.top - 1) == ')' || (S3[i] == '*' || S3[i] == '/')) {
                    Push(&S2, S3[i]);
                    break;
                }
                else if ((S3[i] == '+' || S3[i] == '-') && (*(S2.top - 1) == '+' || *(S2.top - 1) == '-')) {
                    Push(&S2, S3[i]);
                    break;
                }
                else
                    Push(S1, Pop(&S2));
            } while (1);
            break;
        case'(':
            while (*(S2.top - 1) != ')'&&S2.base!=S2.top) 
                Push(S1, Pop(&S2));
            if (S2.base != S2.top)
                Pop(&S2);
            break;
        case')':
            Push(&S2, S3[i]);
            break;
        default:
            Push(S1, S3[i]);
            break;
        }
        i--;
    }
    while (S2.base != S2.top)
        if (*(S2.top - 1) == ')')
            Pop(&S2);
        else
            Push(S1, Pop(&S2));
    SElemType_Char* p;
    p = (*S1).top - 1;
    do {
        printf("%c", *p--);
    } while (p != (*S1).base);
    printf("%c\n", *p);
}
View Code

  

 前缀表达式转后缀表达式
大致思路为从后往前扫描前缀表达式,遇到操作数则入栈,遇到操作符连续出栈并将操作数与操作符按顺序连接后入栈直到扫描完毕
 1 #define MAX_SIZE 100
 2 
 3 typedef char SString[MAX_SIZE+1];
 4 typedef SString SqNode;
 5 typedef struct {
 6     SqNode* base;
 7     int front, rear;
 8 }SqStack;//数据格式
 9 
10 Status InitSqStack(SqStack* T) {
11     (*T).base = (SqNode*)malloc(MAX_SIZE*sizeof(SqNode));
12     (*T).front = 0;
13     (*T).rear = 0;
14     return OK;
15 }//栈初始化
16 
17 Status Push(SqStack_* T, SqNode e) {
18     int i;
19     (*T).base[++(*T).rear][0] = e[0];
20     for (i = 1; i <= e[0]; i++)
21         (*T).base[(*T).rear][i] = e[i];
22     return OK;
23 }//入栈
24 
25 Status Pop(SqStack* T, SqNode* e) {
26     (*e)[0] = (*T).base[(*T).rear][0];
27     for (int i = 1; i <= (*e)[0]; i++)
28         (*e)[i] = (*T).base[(*T).rear][i];
29     (*T).rear--;
30     return OK;
31 }//出栈
32 
33 Status Connect_4_13(SqNode* s, SqNode t1, SqNode t2) {
34     int i, j;
35     i = 1; j = 1;
36     while (i <= t1[0]) {
37         (*s)[i] = t1[i];
38         i++;
39     }
40     while (j <= t2[0])
41         (*s)[i++] = t2[j++];
42     (*s)[0] = t1[0] + t2[0];
43     return OK;
44 }//连接元素
45 
46 Status OutPutSString(SString S) {
47     for (int i = 1; i <= S[0]; i++)
48         printf("%c", S[i]);
49     printf("\n");
50     return OK;
51 }//输出元素
52 
53 void Convert(char* s,SString* T) {
54     (*T)[0] = strlen(s);
55     SqStack S1;
56     InitSqStack(&S1);
57     SString e1, e2, e3;
58     int i = (*T)[0] - 1;
59     while (i>=0) {
60         e3[0] = 1;
61         e3[1] = s[i];
62         switch (s[i]){
63         case'+':
64         case'-':
65         case'*':
66         case'/':
67             Pop_4_13(&S1, &e1);
68             Pop_4_13(&S1, &e2);
69             Connect_4_13(&e1, e1, e2);
70             Connect_4_13(&e1, e1, e3);
71             Push_4_13(&S1, e1);
72             break;
73         default:
74             Push_4_13(&S1, e3);
75             break;
76         }
77         i--;
78     }
79         T = S1.base[1];
80     OutPutSString(T);
81 }//转化
View Code

 

 

 
 
posted @ 2019-08-05 21:42  一位在转行路上的菜鸟  阅读(603)  评论(0编辑  收藏  举报