用栈实现中缀表达式向后缀表达式的转换

写在前面:

只涉及到+、-、*、/、(、)这六种符号(如果有乘方什么的话不要怕麻烦加几个等级就好啦(~ ̄▽ ̄)~)


想法是这样的:

  • 将+、-、*、/四个基本运算符号分成两个等级,+、-级别低,*、/等级较高;而括号单独处理。
  • 将输入的字符串从左到右遍历。
  • 若当前字符是操作数则直接打印;
  • 若当前字符是操作符,先判断栈是否为空,若是,则直接将此操作符压入栈,若不是,则查看当前栈顶元素,若栈顶元素:
  1. 是左括号;(经好心人指正,这里有错误,若栈顶元素是左括号是不应该打印并且弹出的,只有栈顶元素是低级操作符时才会打印弹出!)
  2. 比此操作符级别高;
  3. 与此操作符级别相同;

   则打印并弹出栈顶元素并继续进行上述判断,若栈顶元素不符合上述三项所述(也就是说级别更低时),则直接将操作符压入栈;(在这种情况下,记住最后这个操作符一定会被压入栈内的)

  • 若当前字符是左括号则直接压入栈;
  • 若当前字符是右括号则打印并弹出栈中第一个左括号前的所有操作符,并且将左括号弹出;(这里可以看到:遍历到右括号后就会弹出对应的左括号及这一对括号中间的所有操作符,也就代表着这一级的结束;而且右括号永远不入栈);
  • 字符串遍历结束后,若栈不为空,则弹出栈中所有元素直至栈为空。(注意:最后栈里面应该只有操作符,不可能有括号存在,否则一定有错误!)
  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 
  4 typedef struct Node
  5 {
  6     char ele;
  7     struct Node * next;
  8 }Node;
  9 
 10 typedef Node * Stack;
 11 
 12 Stack MakeStack(void)//新建栈并返回栈顶
 13 {
 14     Stack S = (Node *)malloc(sizeof(Node));
 15     S->next = NULL;
 16     return S;
 17 }
 18 
 19 void MakeNUll(Stack S)//置空栈
 20 {
 21     S->next = NULL;
 22 }
 23 
 24 void Pop(Stack S)//将栈顶弹出
 25 {
 26     Stack temp = S->next;
 27     S->next = temp->next;
 28 }
 29 
 30 void Push(Stack S, char c)//将新节点压入栈
 31 {
 32     Stack temp = (Node *)malloc(sizeof(Node));
 33     temp->ele = c;
 34     temp->next = S->next;
 35     S->next = temp;
 36 }
 37 
 38 Stack FindHead(Stack S)//返回栈顶
 39 {
 40     Stack temp = S->next;
 41     return temp;
 42 }
 43 
 44 void PrintHead(Stack S)//打印栈顶元素
 45 {
 46     Stack temp = S->next;
 47     printf("%c", temp->ele);
 48 }
 49 
 50 int main(void)
 51 {
 52     Stack S = MakeStack();
 53     int i = 0;
 54     char str[200];
 55     printf("Type something.\n");
 56     gets(str);
 57 
 58     while(str[i] != '\0')
 59     {
 60         if(str[i] == '+' || str[i] == '-')//如果str[i]是加号或减号,则先弹出栈顶直到栈已空或栈顶元素为左括号,再将str[i]压入栈
 61         {
 62             if(FindHead(S) == NULL)//若栈已空时,栈顶指针为空,找不到其元素,故须单独讨论
 63             {
 64                 Push(S, str[i]);
 65             }
 66             else
 67             {
 68                 while(FindHead(S)->ele == '+' || FindHead(S)->ele == '-' || FindHead(S)->ele == '*' || FindHead(S)->ele == '/')
 69                 {
 70                     PrintHead(S);
 71                     Pop(S);
 72                 }
 73                 Push(S, str[i]);
 74             }
 75         }
 76 
 77         else if(str[i] == '*' || str[i] == '/')//如果str[i]是乘号或除号,则只有栈顶也是乘除号时才需要弹出
 78         {
 79             if(FindHead(S) == NULL)
 80             {
 81                 Push(S, str[i]);
 82             }
 83             else
 84             {
 85                 while(FindHead(S)->ele == '*' || FindHead(S)->ele == '/')
 86                 {
 87                     PrintHead(S);
 88                     Pop(S);
 89                 }
 90                 Push(S, str[i]);
 91             }
 92         }
 93 
 94         else if(str[i] == '(')//如果str[i]是左括号则直接压入栈
 95         {
 96             Push(S, str[i]);
 97         }
 98 
 99         else if(str[i] == ')')//如果str[i]是右括号,则打印并弹出栈中第一个左括号前的所有操作符,最后将此左括号直接弹出
100         {
101             while(FindHead(S)->ele != '(')
102             {
103                 PrintHead(S);
104                 Pop(S);
105             }
106             Pop(S);
107         }
108 
109         else//如果str[i]不是操作符则直接打印
110         {
111             printf("%c", str[i]);
112         }
113 
114         i++;
115     }
116 
117     while(FindHead(S) != NULL)//遍历后如果栈不为空,则弹出所有操作符
118     {
119         PrintHead(S);
120         Pop(S);
121     }
122 
123     return 0;
124 }

 

posted @ 2017-10-31 20:55  菜菜大魔王  阅读(14384)  评论(7编辑  收藏  举报