数据结构 【实验5 表达式求值】

实验5  表达式求值

实验目的

1.  会定义顺序栈和链栈的结点类型。

2.  掌握栈的插入和删除结点在操作上的特点。

3.  熟悉对栈的一些基本操作和具体的函数定义。

实验内容

程序1

该程序的功能是实现顺序栈的定义和操作。该程序包括定义的栈结构类型以及对每一种栈操作的具体的函数定义和主函数。

/* 定义DataType为int类型 */

typedef int DataType;

 

/* 栈的结点类型 */

#define MAXSIZE  1024  

typedef  struct

{DataType  data[MAXSIZE];

int  top;

}SeqStack;

 

/* 初始化顺序栈 */

SeqStack  SeqStackInit()

 

/* 检查顺序栈是否为空 */

int SeqStackEmpty(SeqStack S)

 

/* 把S置为空栈 */

void ClearStack(SeqStack  S)

 

/* 把元素x压入栈,使其成为新的栈顶元素 */

void SeqStackPush(SeqStack S,DataType x)

 

/* 把栈顶元素弹出 */

DataType SeqStackPop(SeqStack S)

 

/* 取栈顶元素 */

DataType SeqStackGetTop(SeqStack S)

 

/*输出顺序栈中的元素*/

void SeqStackPrint(SeqStack S)

 

程序用顺序栈实现算术表达式求值。

将表达式看成字符串序列,输入语法正确、不含有变量的整数表达式(表达式中的数字限为单位数),利用算符的优先关系,把中序表达式转换为后序表达式后输出,然后求出该后序表达式的值。

例如:输入的表达式为2*(6-4)+8/4

转换后得到的后序表达式为264-*84/+

设计要求:在程序中构造六个子程序分别为

int empty(SeqStack stack); /*检查栈是否为空*/

int operation(char op); /*判断是否为运算符*/

int priority(char op); /*判断运算符的优先权*/

SeqStack push(SeqStack stack,char value); /*入栈*/

SeqStack pop(SeqStack stack,char *value); /*出栈*/

double count(char *backorder); /*计算逆波兰表达式的值*/

 

程序用链栈实现算术表达式求值。(与程序2的基本要求相同)

链栈结点的类型描述如下:

typedef int DataType;

typedef  struct StackNode

{DataType data;

struct StackNode *next;

}StackNode,*LinkedStack; 

 


 

  “运算符优先级表” - 参考博客http://www.jb51.net/article/37289.htm

 

  1 /* 程序1
  2 该程序的功能是实现顺序栈的定义和操作。该程序包括定义的栈结构类型以及对每一种栈操作的具体的函数定义和主函数。
  3 */
  4 #include <stdio.h>
  5 #include <stdlib.h>
  6 /* 定义DataType为int类型 */
  7 typedef int DataType;
  8  
  9 /* 栈的结点类型 */
 10 #define MAXSIZE  1024  
 11 typedef  struct{
 12     DataType  data[MAXSIZE];
 13     int  top;
 14 }SeqStack;
 15  
 16 /* 初始化顺序栈 */
 17 SeqStack  SeqStackInit()
 18 {
 19     SeqStack q;
 20     q.top = -1;
 21     return q;
 22 }
 23  
 24 /* 检查顺序栈是否为空 */
 25 int SeqStackEmpty(SeqStack S)
 26 {
 27     if(S.top==-1)    //栈空
 28         return 1;
 29     else 
 30         return 0;
 31 }
 32  
 33 /* 把S置为空栈 */
 34 void ClearStack(SeqStack  &S)
 35 {
 36     S.top = -1;
 37 }
 38  
 39 /* 把元素x压入栈,使其成为新的栈顶元素 */
 40 void SeqStackPush(SeqStack &S,DataType x)
 41 {
 42     if(S.top==MAXSIZE-1)    //已经满了
 43         printf("入栈失败,栈已满!\n");
 44     else {
 45         S.top++;
 46         S.data[S.top] = x;
 47     }
 48 }
 49  
 50 /* 把栈顶元素弹出 */
 51 DataType SeqStackPop(SeqStack &S)
 52 {
 53     if(S.top==-1){    //栈已空
 54         printf("出栈失败,栈已空!\n");
 55         return 0;
 56     }
 57     else {
 58         DataType x = S.data[S.top--];
 59         return x;
 60     }
 61 }
 62  
 63 /* 取栈顶元素 */
 64 DataType SeqStackGetTop(SeqStack S)
 65 {
 66     return S.data[S.top];
 67 }
 68  
 69 /*输出顺序栈中的元素*/
 70 void SeqStackPrint(SeqStack S)
 71 {
 72     int top = S.top;
 73     while(top!=-1)
 74         printf("%d\n",S.data[top--]);
 75 }
 76 
 77 int Menu()    //显示菜单,返回命令
 78 {
 79     int in;
 80     printf("[1] 检查顺序栈是否为空\n");
 81     printf("[2] 把S置为空栈\n");
 82     printf("[3] 把元素x压入栈,使其成为新的栈顶元素\n");
 83     printf("[4] 把栈顶元素弹出\n");
 84     printf("[5] 取栈顶元素\n");
 85     printf("[6] 输出顺序栈中的元素\n");
 86     printf("[0] 按其它键退出\n");
 87     scanf("%d",&in);
 88     return in;
 89 }
 90 void Reply(int in,SeqStack &S)    //对命令的反应
 91 {
 92     int x;
 93     switch(in){
 94     case 1:
 95         if(SeqStackEmpty(S))
 96             printf("栈为空!\n");
 97         else 
 98             printf("栈未空!\n");
 99         break;
100     case 2:
101         ClearStack(S);    //将S置为空栈
102         printf("已成功置为空栈!\n");
103         break;
104     case 3:
105         printf("请输入你要压栈的元素:\n");
106         scanf("%d",&x);
107         SeqStackPush(S,x);
108         break;
109     case 4:
110         SeqStackPop(S);
111         break;
112     case 5:
113         if(SeqStackEmpty(S))
114             printf("栈当前为空,栈顶无元素!\n");
115         else
116             printf("栈顶元素为:%d\n",SeqStackGetTop(S));
117         break;
118     case 6:
119         if(SeqStackEmpty(S))
120             printf("栈当前为空!\n");
121         else{ 
122             printf("栈中元素为(从顶至下):\n");
123             SeqStackPrint(S);
124         }
125         break;
126     default:
127         exit(1);
128     }
129     system("pause");
130     system("cls");
131 }
132 int main()
133 {
134     SeqStack S = SeqStackInit();
135     while(1){
136         int in = Menu();
137         Reply(in,S);
138     }
139     return 0;
140 }

 

运行截图: 

 

  1 /* 程序2 用顺序栈实现算术表达式求值。
  2 将表达式看成字符串序列,输入语法正确、不含有变量的整数表达式(表达式中的数字限为单位数)
  3 利用算符的优先关系,把中序表达式转换为后序表达式后输出,然后求出该后序表达式的值。
  4 例如:输入的表达式为2*(6-4)+8/4
  5 转换后得到的后序表达式为264-*84/+
  6 设计要求:在程序中构造六个子程序分别为
  7 */
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 /* 定义DataType为int类型 */
 11 typedef char DataType;
 12  
 13 /* 栈的结点类型 */
 14 #define MAXSIZE  1024  
 15 typedef  struct{
 16     char data[MAXSIZE];
 17     int  top;
 18 }SeqStack;
 19 SeqStack op;    //运算符栈和表达式栈
 20 
 21 int Prior[6][6] =    //Prior[lop][rop]
 22 { // 运算符优先级表 
 23  // '+' '-' '*' '/' '(' ')'
 24  /*'+'*/-1,-1,1,1,1,-1,
 25  /*'-'*/-1,-1,1,1,1,-1,
 26  /*'*'*/-1,-1,-1,-1,1,-1,
 27  /*'/'*/-1,-1,-1,-1,1,-1,
 28  /*'('*/1,1,1,1,1,0,
 29  /*')'*/-1,-1,-1,-1,0,-1
 30 };
 31 
 32 int empty(SeqStack stack) /*检查栈是否为空*/
 33 {
 34     if(stack.top==-1)    //栈空
 35         return 1;
 36     else 
 37         return 0;
 38 }
 39 int operation(char op) /*判断是否为运算符*/
 40 {
 41     if('0'<=op && op<='9')    //是单位数字,不是运算符
 42         return 0;
 43     else 
 44         return 1;
 45 }
 46 int priority(char rop) /*判断运算符的优先权*/
 47 {
 48     char lop = op.data[op.top];
 49     int a,b;
 50     switch(lop){
 51     case '+':a=0;break;
 52     case '-':a=1;break;
 53     case '*':a=2;break;
 54     case '/':a=3;break;
 55     case '(':a=4;break;
 56     case ')':a=5;break;
 57     default:break;
 58     }
 59     switch(rop){
 60     case '+':b=0;break;
 61     case '-':b=1;break;
 62     case '*':b=2;break;
 63     case '/':b=3;break;
 64     case '(':b=4;break;
 65     case ')':b=5;break;
 66     default:break;
 67     }
 68     return Prior[a][b];
 69 }
 70 SeqStack push(SeqStack stack,char value) /*入栈*/
 71 {
 72     if(stack.top==MAXSIZE-1)    //已经满了
 73         printf("入栈失败,栈已满!\n");
 74     else {
 75         stack.top++;
 76         stack.data[stack.top] = value;
 77     }
 78     return stack;
 79 }
 80 SeqStack pop(SeqStack stack,char *value) /*出栈*/
 81 {
 82     if(stack.top==-1){    //栈已空
 83         printf("出栈失败,栈已空!\n");
 84         return stack;
 85     }
 86     else {
 87         *value = stack.data[stack.top--];
 88         return stack;
 89     }
 90 }
 91 double count(char *backorder) /*计算逆波兰表达式的值*/
 92 {
 93     struct {
 94         double data[MAXSIZE];
 95         int top;
 96     } ds;    //数栈
 97     ds.top = -1;
 98     int i;
 99     for(i=0;backorder[i];i++)
100         if(operation(backorder[i])){    //是运算符
101             double a,b;
102             b = ds.data[ds.top--];    //从数栈中依次取出两个数
103             a = ds.data[ds.top--];
104             switch(backorder[i]){    //运算并入栈
105             case '+':ds.top++;ds.data[ds.top] = a+b;break;
106             case '-':ds.top++;ds.data[ds.top] = a-b;break;
107             case '*':ds.top++;ds.data[ds.top] = a*b;break;
108             case '/':ds.top++;ds.data[ds.top] = a/b;break;
109             default:break;
110             }
111         }
112         else{    //是数,直接入数栈
113             ds.top++;
114             ds.data[ds.top] = double(backorder[i] - '0');
115         }
116     return ds.data[ds.top];
117 }
118 void trans(char exp[],char backorder[])    //将中序表达式转换成后缀表达式,存储一字符串中
119 {
120     int index=0;
121     int len = 0;
122     while(exp[index]){
123         if(operation(exp[index])){    //是运算符
124             if(empty(op)){    //如果运算符栈为空,直接入栈
125                 op = push(op,exp[index++]);
126             }
127             else{    //运算符栈不为空,与将该运算符与栈顶运算符比较
128                 char c;
129                 switch(priority(exp[index])){
130                 case 1:    //当前运算符比栈顶运算符优先级高
131                     op = push(op,exp[index++]);
132                     break;
133                 case 0:    //运算符优先级相等。只出现在栈顶为'('和当前为')'的情况
134                     op = pop(op,&c);
135                     index++;
136                     break;
137                 case -1:    //当前运算符优先级低
138                     op = pop(op,&c);    //退栈 
139                     backorder[len++] = c;    //将运算符放入字符串中
140                     break;
141                 default:break;
142                 }
143             }
144         }
145         else{    //是数字。直接压栈
146             backorder[len++] = exp[index++];    //将数字放入字符串中
147         }
148     }
149     while(!empty(op)){    //如果运算符栈不为空,全部出栈
150         char c;
151         op = pop(op,&c);    //退栈 
152         backorder[len++] = c;    //将运算符放入字符串中
153     }
154     backorder[len] = '\0';
155 }
156 void print(char backorder[])    //输出表达式栈中的式子
157 {
158     int i;
159     for(i=0;backorder[i];i++)
160         printf("%c",backorder[i]);
161     printf("\n");
162 }
163 int main()
164 {
165     char exp[MAXSIZE];
166     char backorder[MAXSIZE];
167     printf("[1] 请输入中缀表达式:\n");
168     while(scanf("%s",exp)!=EOF){
169         //初始化
170         op.top = -1;
171         //输出转换后的后缀表达式
172         trans(exp,backorder);
173         printf("[2] 其后缀表达式为:\n");
174         print(backorder);
175         //计算后缀表达式的结果
176         printf("[3] 后缀表达式的结果:\n");
177         printf("%lf\n",count(backorder));
178         //为下一次输入做准备
179         printf("\n");
180         printf("请输入中缀表达式:\n");
181     }
182     return 0;
183 }

  运行截图:

 

 

  1 /* 程序3 用链栈实现算术表达式求值。(与程序2的基本要求相同)
  2 */
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 
  6 /* 栈的结点类型 */
  7 #define MAXSIZE  1024
  8 
  9 //链栈结点的类型描述如下:
 10 typedef char DataType;
 11 typedef  struct StackNode{
 12     DataType data;
 13     struct StackNode *next;
 14 } StackNode,*LinkedStack;
 15 
 16 LinkedStack op;    //运算符栈和表达式栈
 17 
 18 int Prior[6][6] =    //Prior[lop][rop]
 19 { // 运算符优先级表 
 20  // '+' '-' '*' '/' '(' ')'
 21  /*'+'*/-1,-1,1,1,1,-1,
 22  /*'-'*/-1,-1,1,1,1,-1,
 23  /*'*'*/-1,-1,-1,-1,1,-1,
 24  /*'/'*/-1,-1,-1,-1,1,-1,
 25  /*'('*/1,1,1,1,1,0,
 26  /*')'*/-1,-1,-1,-1,0,-1
 27 };
 28 
 29 int empty(LinkedStack &stack) /*检查栈是否为空*/
 30 {
 31     if(stack->next==NULL)    //栈空
 32         return 1;
 33     else
 34         return 0;
 35 }
 36 int operation(char op) /*判断是否为运算符*/
 37 {
 38     if('0'<=op && op<='9')    //是单位数字,不是运算符
 39         return 0;
 40     else 
 41         return 1;
 42 }
 43 int priority(char rop) /*判断运算符的优先权*/
 44 {
 45     char lop = op->next->data;
 46     int a,b;
 47     switch(lop){
 48     case '+':a=0;break;
 49     case '-':a=1;break;
 50     case '*':a=2;break;
 51     case '/':a=3;break;
 52     case '(':a=4;break;
 53     case ')':a=5;break;
 54     default:break;
 55     }
 56     switch(rop){
 57     case '+':b=0;break;
 58     case '-':b=1;break;
 59     case '*':b=2;break;
 60     case '/':b=3;break;
 61     case '(':b=4;break;
 62     case ')':b=5;break;
 63     default:break;
 64     }
 65     return Prior[a][b];
 66 }
 67 LinkedStack push(LinkedStack &stack,char value) /*入栈*/
 68 {
 69     LinkedStack p = (LinkedStack)malloc(sizeof(StackNode));
 70     p->data = value;
 71     p->next = stack->next;
 72     stack->next = p;
 73     return stack;
 74 }
 75 LinkedStack pop(LinkedStack &stack,char *value) /*出栈*/
 76 {
 77     if(stack->next==NULL){    //栈已空
 78         printf("出栈失败,栈已空!\n");
 79         return stack;
 80     }
 81     else {
 82         LinkedStack p = stack->next;
 83         stack->next = p->next;
 84         *value = p->data;
 85         free(p);
 86         return stack;
 87     }
 88 }
 89 double count(char *backorder) /*计算逆波兰表达式的值*/
 90 {
 91     typedef struct DigitStack{
 92         double data;
 93         DigitStack *next;
 94     } DigitStack,*LinkedDS;    //数栈
 95     LinkedDS ds = (LinkedDS)malloc(sizeof(DigitStack));
 96     LinkedDS p;
 97     ds->next = NULL;    //初始化
 98     int i;
 99     for(i=0;backorder[i];i++)
100         if(operation(backorder[i])){    //是运算符
101             double a,b;
102             p = ds->next;    //从数栈中依次取出两个数
103             ds->next = p->next;
104             b = p->data;
105             free(p);
106             p = ds->next;
107             ds->next = p->next;
108             a = p->data;
109             free(p);
110             p = (LinkedDS)malloc(sizeof(DigitStack));
111             switch(backorder[i]){    //运算并入栈
112             case '+':
113                 p->data = a+b;
114                 p->next = ds->next;
115                 ds->next = p;
116                 break;
117             case '-':
118                 p->data = a-b;
119                 p->next = ds->next;
120                 ds->next = p;
121                 break;
122             case '*':
123                 p->data = a*b;
124                 p->next = ds->next;
125                 ds->next = p;
126                 break;
127             case '/':
128                 p->data = a/b;
129                 p->next = ds->next;
130                 ds->next = p;
131                 break;
132             default:break;
133             }
134         }
135         else{    //是数,直接入数栈
136             p = (LinkedDS)malloc(sizeof(DigitStack));
137             p->data = double(backorder[i] - '0');
138             p->next = ds->next;
139             ds->next = p;
140         }
141     return ds->next->data;
142 }
143 void trans(char exp[],char backorder[])    //将中序表达式转换成后缀表达式,存储一字符串中
144 {
145     int index=0;
146     int len = 0;
147     while(exp[index]){
148         if(operation(exp[index])){    //是运算符
149             if(empty(op)){    //如果运算符栈为空,直接入栈
150                 op = push(op,exp[index++]);
151             }
152             else{    //运算符栈不为空,与将该运算符与栈顶运算符比较
153                 char c;
154                 switch(priority(exp[index])){
155                 case 1:    //当前运算符比栈顶运算符优先级高
156                     op = push(op,exp[index++]);
157                     break;
158                 case 0:    //运算符优先级相等。只出现在栈顶为'('和当前为')'的情况
159                     op = pop(op,&c);
160                     index++;
161                     break;
162                 case -1:    //当前运算符优先级低
163                     op = pop(op,&c);    //退栈 
164                     backorder[len++] = c;    //将运算符放入字符串中
165                     break;
166                 default:break;
167                 }
168             }
169         }
170         else{    //是数字。直接压栈
171             backorder[len++] = exp[index++];    //将数字放入字符串中
172         }
173     }
174     while(!empty(op)){    //如果运算符栈不为空,全部出栈
175         char c;
176         op = pop(op,&c);    //退栈 
177         backorder[len++] = c;    //将运算符放入字符串中
178     }
179     backorder[len] = '\0';
180 }
181 void print(char backorder[])    //输出表达式栈中的式子
182 {
183     int i;
184     for(i=0;backorder[i];i++)
185         printf("%c",backorder[i]);
186     printf("\n");
187 }
188 void Destroy(LinkedStack &op)
189 {
190     while(op->next){
191         LinkedStack p = op->next;
192         op->next = p->next;
193         free(p);
194     }
195 }
196 int main()
197 {
198     char exp[MAXSIZE];
199     char backorder[MAXSIZE];
200     op = (LinkedStack)malloc(sizeof(StackNode));
201     printf("[1] 请输入中缀表达式:\n");
202     while(scanf("%s",exp)!=EOF){
203         //初始化
204         op->next = NULL;
205         //输出转换后的后缀表达式
206         trans(exp,backorder);
207         printf("[2] 其后缀表达式为:\n");
208         print(backorder);
209         //计算后缀表达式的结果
210         printf("[3] 后缀表达式的结果:\n");
211         printf("%lf\n",count(backorder));
212         //为下一次输入做准备
213         Destroy(op);
214         printf("\n");
215         printf("请输入中缀表达式:\n");
216     }
217     return 0;
218 }

  运行截图:

 

 

Freecode : www.cnblogs.com/yym2013

posted @ 2014-04-22 21:43  Freecode#  阅读(1516)  评论(0编辑  收藏  举报