后缀表达式转换及求值
第二章 前缀表达式、中缀表达式、后缀表达式的转换

Stack
* ( +
a b c
Outpu t
* + d e
a+b*c+(d*e+f)*g
11. 读到“+”,弹出“*”并输出,然后将“+”压入栈中。 12.读到f,直接输出。 此时栈和输出的情况如下:
Stack
* ( +
a b c * +d e * f
Outpu t
a+b*c+(d*e+f)*g
Stack
++ a * b c * + * d e f g
Outpu t
任务二:将下列中缀表达式转换为前缀表达式
中缀表达式 前表达式
• 1+((2+3)*4)-5 • a-(b + c/d)*e • a + b*(c + d/e) • a*(b + c)-d
•? •? •? •?
思考
中缀表达式到前缀表达式、 后缀表达式是否还有其他的转换 方法?
Stack
* +
a b c
Outpu t
a+b*c+(d*e+f)*g
6.读到“+”,因为栈顶元素“*”优先级比“+”高,所以弹出“*” 并输出,同理,栈中下一个元素“+”优先级与读到的操作符“+”一样, 所以也要弹出并输出。然后再将读到的“+”压入栈中。
此时栈和输出的情况如下:
Stack
+
a b c
前缀表达式的计算机求值举例
前缀表达式“-*+3456” (1)从右至左扫描,将6、5、4、3压入堆栈; (2)遇到+运算符,因此弹出3和4(3为栈顶元素、4为次顶元素), 计算出3+4的值,得7,再将7入栈;
后缀表达式求值过程

后缀表达式求值过程嘿,朋友!今天咱们来唠唠后缀表达式求值这个超有趣的事儿。
你可能会想,这后缀表达式是啥呀?就像你看到一个神秘的密码,其实只要掌握了方法,求值就像解开密码锁一样简单又好玩。
我先给你说说啥是后缀表达式吧。
咱平常看到的表达式,像“3 + 4”这种中缀表达式,操作符在中间。
而后缀表达式呢,操作符在操作数的后面,就像“3 4 +”。
这看起来有点怪,可它在计算机处理起来可就方便多啦。
那怎么求值呢?咱得有个小工具,那就是栈。
栈就像一个小盒子,不过这个小盒子有点特别,先放进去的东西后拿出来,就像你往一个窄口瓶子里塞东西,先塞进去的在底下,最后才能拿出来。
比如说咱们要计算“4 5 * 6 +”这个后缀表达式的值。
我和我那聪明的小伙伴小明就开始啦。
小明负责操作栈,我来指挥。
首先看到“4”,小明就把4这个数字放到栈里。
这就像把一个小宝贝放进那个神秘的盒子里。
接着看到“5”,小明也把5放进栈里。
现在栈里就有4和5啦,就像两个小伙伴在盒子里安静地待着。
然后看到“*”这个操作符,这时候就像魔法要开始啦。
小明从栈里拿出5和4(注意哦,是先拿5,因为栈的特性),然后计算4乘以5等于20,再把20放进栈里。
哇,这就像把两个小伙伴融合成了一个超级小伙伴呢!再看到“6”,小明又把6放进栈里。
现在栈里有20和6啦。
最后看到“+”,小明又从栈里拿出6和20,计算20加6等于26,这就是最后的结果啦。
是不是感觉很神奇呢?就像一场奇妙的数学之旅。
再来看一个复杂点的例子吧。
像“3 4 + 2 * 5 -”。
我和我的另一个朋友小花来操作这个。
小花可认真啦。
先看到“3”,放进栈里,再看到“4”,也放进栈里。
看到“+”的时候,小花从栈里拿出4和3,计算3加4等于7,把7放进栈里。
这时候就像我们搭建了一个小积木塔的一部分。
接着看到“2”,放进栈里。
看到“*”的时候,小花从栈里拿出2和7,计算7乘以2等于14,再把14放进栈里。
最后看到“5”,放进栈里,看到“ - ”的时候,小花从栈里拿出5和14,计算14减5等于9。
后缀表达形式

后缀表达形式后缀表达式(Reverse Polish Notation,简称RPN)是一种数学表达式的书写方式,与传统的中缀表达式相比具有简洁、易于计算的特点。
本文将介绍后缀表达式的定义、转换方法以及其在计算机科学和数学领域的应用。
一、后缀表达式的定义和特点后缀表达式是一种运算符位于操作数之后的数学表达式。
它的主要特点是省略了括号,并且操作符的优先级通过操作符本身的位置来确定。
例如,中缀表达式“3+4*5”可以转换为后缀表达式“345*+”。
后缀表达式的优势在于它避免了使用括号来标识运算符的优先级,使得表达式的计算更加简洁明了。
同时,后缀表达式的计算过程也更加直观,只需要从左到右依次处理每个操作数和操作符即可。
二、中缀表达式转换为后缀表达式的方法将中缀表达式转换为后缀表达式的方法主要有两种:栈的应用和递归的应用。
1. 栈的应用:通过使用一个运算符栈来实现转换。
遍历中缀表达式中的每个元素,按照以下规则进行处理:- 如果是操作数,则输出到后缀表达式中;- 如果是左括号,则将其压入运算符栈中;- 如果是右括号,则将运算符栈中的运算符依次弹出并输出,直到遇到左括号;- 如果是运算符,则将其与运算符栈栈顶的运算符进行比较:- 如果运算符栈为空或栈顶为左括号,则将当前运算符压入运算符栈中;- 如果当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符压入运算符栈中;- 否则,将运算符栈栈顶的运算符弹出并输出,然后继续比较当前运算符与新的栈顶运算符的优先级。
2. 递归的应用:通过递归地处理中缀表达式的每个元素来实现转换。
遍历中缀表达式中的每个元素,按照以下规则进行处理:- 如果是操作数,则输出到后缀表达式中;- 如果是运算符,则判断当前运算符与前一个运算符的优先级关系:- 如果当前运算符的优先级大于前一个运算符的优先级,则将当前运算符输出到后缀表达式中;- 否则,将前一个运算符输出到后缀表达式中,然后继续递归处理当前运算符。
C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。
⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。
1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。
因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。
⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。
⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。
举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。
2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。
在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。
3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。
他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。
因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。
注意:逆波兰记法并不是简单的波兰表达式的反转。
因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。
前缀、中缀、后缀表达式的相互转换方法

前缀、中缀、后缀表达式的相互转换⽅法前缀式、中缀式、后缀式相互转换⼀. 中缀式转化成前缀式和后缀式:⼀个中缀式到其他式⼦的转换⽅法这⾥我给出⼀个中缀表达式a +b *c - (d +e )第⼀步:按照运算符的优先级对所有的运算单位加括号式⼦变成:( ( a + ( b * c ) ) - ( d + e ) )第⼆步:转换前缀与后缀表达式中缀转前缀:把运算符号移动到对应的括号前⾯则变成:- ( + ( a * ( b c ) ) + ( d e ) )把括号去掉:- + a * b c + d e 前缀式⼦出现中缀转后缀:把运算符号移动到对应的括号后⾯则变成:( ( a ( b c ) * ) + ( d e ) + ) -把括号去掉:a b c * + d e + - 后缀式⼦出现⼆. 前缀式转化成中缀式:+ a * b c + d e从后往前遇到运算符,将其与后⾯两个运算数结合,加上括号,当成新的运算数(例如:* b c 加上括号,变成 ( * b c )⼀个整体,作为运算数)变成:( - ( + a ( * b c ) ) ( + d e ) )将运算符加在括号内运算数中间。
变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)三. 后缀式转化成中缀式:a b c * + d e + -从前往后遇到运算符,将其与前⾯两个运算数结合,加上括号,当成新的运算数变成:( ( a ( b c * ) + ) ( d e + ) - )将运算符加在括号内运算数中间。
变成:( ( a + ( b * c ) ) - ( d + e ) )去掉部分括号:a + b * c - ( d + e )(最后去掉的是不影响运算式含义的多余括号)。
数据结构后缀表达式转换过程

数据结构后缀表达式转换过程在计算机科学中,数据结构是非常重要的一部分,而表达式的转换则是其中一个常见且关键的操作。
今天,咱们就来深入探讨一下后缀表达式的转换过程。
先来说说啥是后缀表达式。
简单来讲,后缀表达式就是把运算符放在操作数的后面。
比如说,对于常见的中缀表达式“2 +3”,它的后缀表达式就是“2 3 +”。
那为啥要研究后缀表达式的转换呢?这是因为后缀表达式在计算机计算时更方便、更高效。
那后缀表达式是怎么从常见的中缀表达式转换过来的呢?这就得提到一个重要的工具——栈。
咱们来一步步看这个转换过程。
假设咱们有一个中缀表达式,比如“3 +4 2 1”。
第一步,咱们要把这个中缀表达式中的数字和运算符一个一个地读进来。
当读到数字的时候,直接输出。
比如说,一开始读到 3,那就直接把 3 输出。
当读到运算符的时候,这就得和栈打交道了。
如果栈为空,那就把这个运算符直接入栈。
要是栈不为空,那就得比较当前运算符和栈顶运算符的优先级。
如果当前运算符的优先级高于栈顶运算符,那就把当前运算符入栈;要是当前运算符的优先级低于或者等于栈顶运算符,那就把栈顶运算符出栈并输出,然后再继续比较当前运算符和新的栈顶运算符,直到当前运算符的优先级高于栈顶运算符或者栈为空,再把当前运算符入栈。
比如说,读到“+”的时候,栈为空,那就把“+”入栈。
接着读到“”,因为“”的优先级高于“+”,所以把“”入栈。
再读到“”,因为“”的优先级低于“”,所以把“”出栈并输出,然后再比较“”和“+”,因为“”的优先级高于“+”,所以把“”入栈。
当整个中缀表达式都读完之后,把栈中剩下的运算符依次出栈并输出。
按照这个步骤,咱们就能把“3 +4 2 1”这个中缀表达式转换为后缀表达式“3 4 2 +1 ”。
在实际的编程中,实现这个转换过程可能会用到一些数据结构和算法的知识。
比如说,用数组或者链表来实现栈,用循环和条件判断来处理表达式的读取和转换。
再举个例子,“(2 +3) 4 5”。
中缀表达式转后缀表达式并计算结果(c语言版)
中缀表达式转后缀表达式中缀表达式转后缀表达式的规则。
1.遇到操作数:直接输入到后缀表达式栈2.遇到运算符,直接入操作符栈3.遇到左括号:直接将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈6.最终将操作符栈中的元素依次出栈,输出到后缀表达式栈。
以下是自己写的代码。
亲测没有问题。
(模拟一个计算器,可以带括号,中间可以空格,只支持整数输入,但是输出结果精确到小数后6位)#include "stdio.h"#define MAX_LEN 100typedef struct cal{unsigned char isOper;//是否是操作数1,操作符0.操作数double Num; //值。
或者是操作符的ASCII值}STRUCT_CAL;#define IS_NUM 0x00#define IS_OPER 0x01STRUCT_CAL stackCal[MAX_LEN];STRUCT_CAL stackCalBack[MAX_LEN];unsigned char topCal;char stackOper[MAX_LEN];unsigned char topOper;/****************************************************************** 堆栈初始化*****************************************************************/void stackInit(void){int i;for(i=0;i<MAX_LEN;i++){stackCal[i].isOper = 0;stackCal[i].Num = 0;stackOper[i] = 0;}topCal = topOper = 0;}/***************************************************************** * 返回堆栈的栈顶,返回后栈顶减一*****************************************************************/ STRUCT_CAL * stackCalPop(void){if(topCal == 0)return (STRUCT_CAL *)0;return stackCal+(--topCal);}/***************************************************************** * 计算表达式入栈*****************************************************************/void stackCalPush(double num, unsigned char isOper){if(topCal>=MAX_LEN)return;stackCal[topCal].Num = num;stackCal[topCal].isOper= isOper;topCal++;}/***************************************************************** * 操作符出栈*****************************************************************/char stackOperPop(void){if(topOper == 0)return 0;return stackOper[--topOper];}/****************************************************************** 操作符入栈*****************************************************************/void stackOperPush(char oper){if(topOper >=MAX_LEN)return;stackOper[topOper++] = oper;}/****************************************************************** 比较两个sour sour1 的优先级* 1 sour >= sour1 直接入操作符栈* 0 sour < sour1 直接入计算表达式栈*****************************************************************/ unsigned char comparPrior(char sour, char sour1){if(sour =='\0' ||sour1 == '\0') return 1;switch(sour){case '+':case '-':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-' ){return 0;}else{return 1;}break;case '*':case '/':if(sour1 == '*' ||sour1 == '/'||sour1 == '+' ||sour1 == '-'||sour1 == '('){return 1;}else{return 0;}break;default:return 1;break;}}/****************************************************************** 将输入的字符串转换为栈*****************************************************************/void StrToCal(char *pStr){int tmpNum = 0;char tmpOper;char islastNum = 0;//判断上一个字符是什么。
表达式求值算法
表达式求值算法表达式求值算法是计算机科学中的重要概念之一,用于计算数学表达式的结果。
在编程语言中,表达式求值是一项基本的操作,并且经常在计算过程中需要用到。
本文将介绍一些常见的表达式求值算法及其实现。
1. 逆波兰表达式法逆波兰表达式法是一种用于计算数学表达式的算法,它使用后缀表达式(也称为逆波兰表达式)来表示表达式。
逆波兰表达式是将操作符放在操作数之后的一种表示方法。
对于任意一个数学表达式,都可以通过将中缀表达式转换为后缀表达式,然后使用栈结构计算得到结果。
逆波兰表达式法的优点是计算顺序明确,不需要考虑运算符的优先级和括号的处理。
2. 中缀表达式转后缀表达式法中缀表达式是我们常见的数学表达式,如 3 + 4 * 5。
在中缀表达式中,操作符的优先级和括号起着很大的作用。
为了将中缀表达式转换为后缀表达式,我们需要使用到栈结构。
具体的算法如下:- 遍历中缀表达式的每个元素。
- 如果是操作数,则直接输出。
- 如果是操作符,则判断其与栈顶操作符的优先级,决定是否将其压入栈。
- 如果是左括号,则直接压入栈。
- 如果是右括号,则依次弹出栈顶操作符,并输出,直到遇到左括号为止。
- 遍历完表达式后,如果栈不为空,则依次弹出栈顶操作符,并输出。
3. 后缀表达式求值法后缀表达式(逆波兰表达式)的求值方法相对简单。
我们可以使用栈结构来计算后缀表达式的结果。
具体的算法如下:- 遍历后缀表达式的每个元素。
- 如果是操作数,则将其压入栈。
- 如果是操作符,则弹出栈顶的两个操作数,执行相应的计算,并将结果压入栈。
- 遍历完后缀表达式后,栈中最后剩下的元素即为计算结果。
4. 二叉树表示法除了逆波兰表达式法和中缀表达式法,我们还可以使用二叉树来表示表达式,并通过遍历二叉树来计算表达式的结果。
具体的算法如下:- 构建二叉树,将表达式的操作符作为根节点,将操作数作为叶节点。
- 通过后序遍历二叉树,计算出每个子树的值,并将结果返回给其父节点。
四则运算解析及计算
四则运算解析及计算四则运算是中缀表达式,需要将其转化为后缀表达式。
原因是计算中缀表达式很困难。
明确运算符的优先级:优先级(数字越⼤,优先级越⾼)运算符2+-1*/0()格式化四则表达式输⼊的表达式可能出现⽆⽤的字符,需要去除否则影响下⾯的判断逻辑。
处理⽅法为,遍历整个字符串,删除换⾏、空格和制表符。
后缀表达式转化中缀表达式转化为后缀表达式的基本步骤如下:1.初始化⼀个运算符栈。
2.从输⼊的表达式的字符串中依次从左向右每次读取⼀个字符。
3.如果当前读取的字符是操作数,则直接填写到后缀表达式中 (如果后缀表达式末尾已经有操作数,需要使⽤逗号分隔开)。
4.如果当前字符是“(”左括号,将其压⼊运算符栈。
5.如果当前字符为运算符,则分三种情况:(1)当前运算符栈为空,将其压⼊运算符栈。
(2)当前运算符的优先级⼤于栈顶元素,则将此运算符压⼊运算符栈;否则,弹出栈顶的运算符到后缀表达式,反复弹出,直到该运算符优先级⼤于栈顶元素或者栈为空时,然后将当前运算符压栈。
回到步骤2继续读取。
(3)如果上⼀次读到的也是运算符,则中缀表达式错误直接返回6.如果当前字符是“)”右括号,反复将栈顶元素弹出到后缀表达式,直到栈顶元素是左括号“(”为⽌,并将左括号从栈中弹出丢弃。
如果找不到“(”则中缀表达式错误直接返回7.如果读取还未完成,回到步骤2.8.如果读取完成,则将栈中剩余的运算符依次弹出到后缀表达式。
※如果表达式中出现负数或者⼩数,需对负数和⼩数点采取特殊处理:(1)如果是负数,需要把“-”⼀起存放到后缀表达式中同时还要添加⼀个特殊字符“!”⽤于标记负数。
两种情况下出现“-”可判定为负数。
A.“-”为⾸字符且下⼀个字符为数字;B.“-”为⾮⾸字符且位于“(”之后且后⼀个字符为数字;(2)如果有⼩数,需要记录⼩数点的位数举例:输⼊的四则表达式是 -15. *((-5+.6)*87-(-4.592+3.33)*8)处理后的后缀表达式为:!-15.,!-5,.6,+87,*!-4.592,3.33,+8,*-*后缀表达式求值:从左到右读取1、设置⼀个栈,开始时,栈为空;2、然后从左到右读取后缀表达式,若遇操作数,则进栈;3、若遇运算符,则从栈中退出两个元素,先退出的放到运算符的右边,后退出的放到运算符左边,运算后的结果再进栈,直到后缀表达式扫描完毕;4、最后,栈中仅有⼀个元素,即为运算的结果。
c语言基于二叉树的表达式求值算法
c语言基于二叉树的表达式求值算法C语言中,基于二叉树的表达式求值算法主要包括两部分:中缀表达式转换为后缀表达式和后缀表达式求值。
1.中缀表达式转换为后缀表达式中缀表达式是我们常见的数学表达方式,例如3 + 4 * 2 - 5。
为了方便计算机求值,我们需要将中缀表达式转换为后缀表达式,也叫做逆波兰表达式。
转换的过程使用栈数据结构来实现。
具体算法如下:1.定义一个栈和一个结果字符串,栈用于存储操作符,结果字符串用于保存后缀表达式。
2.从左到右遍历中缀表达式的每一个字符。
3.如果当前字符是数字,直接将其加入结果字符串。
4.如果当前字符是左括号"(",将其入栈。
5.如果当前字符是右括号")",则依次将栈顶的操作符弹出并加入结果字符串,直到遇到左括号为止,同时将左括号从栈中弹出。
6.如果当前字符是操作符,需要将栈中优先级比当前操作符高或者相等的操作符弹出并加入结果字符串,然后将当前操作符入栈。
7.遍历完所有字符后,将栈中剩余的操作符依次弹出并加入结果字符串。
8.最终结果字符串就是后缀表达式。
例如,对于中缀表达式3 + 4 * 2 - 5,转换为后缀表达式为3 4 2 * + 5 -2.后缀表达式求值后缀表达式求值算法使用栈数据结构来实现。
具体算法如下:1.定义一个栈,用于存储操作数。
2.从左到右遍历后缀表达式的每一个字符。
3.如果当前字符是数字,则将其转换为对应的整数并入栈。
4.如果当前字符是操作符,则从栈中弹出两个操作数,先弹出的作为右操作数,后弹出的作为左操作数,根据操作符进行运算,得到结果后入栈。
5.遍历完所有字符后,栈顶的数字即为最终的结果。
例如,对于后缀表达式3 4 2 * + 5 -,求值的过程如下:1.入栈3。
2.入栈4。
3.入栈2。
4.弹出2和4,计算4 * 2 = 8,将8入栈。
5.弹出8和3,计算3 + 8 = 11,将11入栈。
6.入栈5。
7.弹出5和11,计算11 - 5 = 6,得到最终结果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
12,98,78,3,2,/,+,* , -
并算出正确结果
-7730 (注意:整数运算,3/2 =1 )
后缀表达式栈中元素结构的设计:
后缀表达式: 12,98,78,3,2,/,+,* , -
算子: 12,98,78,3,2 运算符号: +,-,*,/,*, ( , )
后缀表达式转换及求值
丁鑫 dingxin@
作业要求
实现一个将包含四则运算、括号的正整数表达 式转换为后缀形式。
实现带括号的正整数的四则运算表达式的求 值。要求能实现对多位整数进行处理的。
对错误格式的表达式进行判别并给出错误信 息
示例
输入字符串:12 - 98*(78+3/2)
运算符优先关系矩阵
理解矩阵中函数返回值的含义
“#” ,程序中共出现两次,
输入字符串尾 运算符栈的栈底,
“3”, 出现1次
“(”可以压栈, “)”从不压栈
从中缀表达式求得后缀式的规则
(1) (2) (3) 设立操作符栈 设表达式的结束符为“#”, 设运算符栈的栈底为“#”; 当程序的出口是字符串的“#”遇到“#”,计算结束 若当前字符串是个操作数 则直接发送给后缀式。 否则:若当前运算符的优先数高于栈顶运算符,则进栈; 否则:退出栈顶运算符发送给后缀式; goto (3); (说明:循环伪码,尽量在实现上用goto语句) (4) “(” 对它之前后的运算符起隔离作用,“)”可视为自相应左括弧开始 的表达式的结束符。相遇则自动取消。
计算后缀表达式
计运算符优先关系矩阵
“#”, 0,1,2,3,4含义不清楚,
尽量不要使用goto语句
加强程序的可读性
Thank you !!!