电子表格解题报告
http://www.mydrs.org 7/31/2001 大榕树
题目:
本题的编程目标是将一个有表达式和数字组成的电子表格中的表达式求知,如果可以求知的表达式用球和结果代换,不能求和的表达式则在该表达式的位置上述出"ERROR"。为了表达方便,在本报告中将表格内的每一个元素叫做单元格。
算法概要:
由于题目不要求考虑表达式循环引用的情况,因此本题的算法就是每一次从头到尾将表达式遍历一边,将表达式内已知的部分的用数字代换,依次不断求值直到有一次求值时表格内的每一个单元格的值都没有改变为止。
数据结构:
首先,电子表格肯定是用二维数组表示。原题输入的表达式的形式是字符串,由于程序要不断求解,在求解的过程中要反复讲字符串中的坐标表示转换为数组的坐标,程序实现不易。所以在读入数据的时候就对数据做出处理。观察本题输入的内容,发现表达式可以分成两个部分:数字和字母,数字部分也就是已知部分,字母部分表示了表达之间的依赖关系。这样由纯数字构成的单元格也可以看成是没有字母部分的表达式。而且题目中的表达式只能用"+"、'-'号连接,由于这两个运算符优先级先等,所以可以表达式可以用线性的关系来表示。
数据的存储方式如下图:
Total[I,j]表示第I行第j列的单元格上的表达式的数字部分。
Tabel[I,j]表示第I行第j列的单元格上的表达式的字母部分,是一个链表的头指针,这个链表中的每一项就表式表达式引用了另外的一个单元格的数据,链表最后一个元素的next指向nil。如果Tabel[I,j]=nil,那么这个表达式没有字母部分。Tabel[I,j].x、Tabel[I,j].y分别表示表达式中需要的数据的单元格的位置。Tabel[I,j].f表示引用这一个单元格数据时用的符号(+或-)。
表达式:
程序实现:
首先在读入数据的时候建立表格Total和Tabel。以后每一次计算的时候对每一个单元格对应的链表遍历一遍,如果链表中的一个节点所对应的单元格已经完成了计算,那么就把这个单元格的数据(Total)加入正在求解的单元格中,并且在链表中删除这一个节点。根据以上规则反复对表格求解,直到有一次求解时不比上一次得到更多的单元格的结果为止。
输出的时候如果一个节点的链表指针不是nil,那么在这个单元格的位置上输出ERROR。
程序优化:
1、 节约空间。原本链表每个节点占用7个字节,x、y、f各一个,next四个字节。而实际上f可以不用存储,可以用x的正负表示f。比如x=-3,y=3,则表示采用(|x|,y)这格单元格的值,符号是|x|/x=-1。这样可以节约一个字节。不过在本题的要求范围内意义不大。
2、 多向求解。原来程序的求解方式是从上至下从左至右求解。但是有的数据的利用方向正好和这个方向相反,就要比较多的时间。采用多向求解后,就可以用"从上至下从左至右"、"从上至下从右至左"、"从下至上从左至右"、"从下至上从右至左"四个方向求解。但是只对于特殊数据有效果,一般数据效果不明显。
|