1 题目要求
- 链表的头结点值为-1,其余结点依次存放数据,各结点最多放四位整数,如下图表示233238766:
- 利用上述数据结构解决大整数的表示,以及加法、减法运算(用两个链表表示操作数)。
- 将上述数据结构应用于10位以上求素数问题和阶乘问题。
2 需求分析
本题是利用单向循环链表解决大整数的相关问题。首先要构建一个有数据域和指针域的结点类,再构建一个有头节点、尾结点和存储数据所需结点个数的链表类。
- 由于int型变量最多可以存放十位整数,所以大整数输入时应定义为string类,存入链表时再转化为整型。
- 需要解决如何将多位整数从低位开始每四位存入链表,且需将string类转化为int类再存入链表的data域。
- 加法减法运算需要考虑进位和借位问题,并将所得结果存储到另一个单向循环链表中。
- 输出存储在链表中的大整数时由于是单向循环链表低位在表头高位在表尾,输出时需要将在链表中所得的数据倒置,考虑使用STL中的vector容器。当某个结点数值为0时要控制输出补齐四个0。
- 大数阶乘考虑使用加法运算来实现乘法。由于参与循环的数据是链表类的,需要重载≤和++运算符确保循环条件的实现。重载≤运算符时需要从高位到低位依次比较仍需借助vector容器实现。
- 判断大数是否是素数需要利用除法实现。因为除法是从高位开始运算,需要重载[]运算符从而可以直接获取链表中某个结点所存储的数据。除法中还需要解决借位问题。判断是否是素数时的循环停止条件需要缩小,减少程序运行时间。
3 方案设计
1. 构造结点类。
结点类包含两个公有型的变量:最多存放四位整数的数据域data,指向下一个结点的指针类型的指针域next。一个公有型的成员函数:构造函数对数据域和指针域进行初始化。
2. 构造链表类。
链表类包含三个私有型的变量:结点类型的头指针head和尾指针tail。九个公有型的成员函数:无参构造函数,构造函数,加法函数Add(),减法函数Sub(),返回结点数的函数Length(),输出函数Display(),四个运算符的重载函数,求阶乘的函数Factor()。
3. 链表类的构造函数List(const string &str);
在构造函数中实现将大数每四位由string类型转化为int类型并且利用尾插法插入链表。定义一个int类型的变量len和count,len存储string类型的大数的长度,count存储该大数所需要的结点的个数。当len%4有余数时count=len/4+1,当len%4没有余数时count=len/4。利用所得count数进行循环尾插,利用string类中的substr函数获得四位子串并转化为整型依此存储结点的数据域中,完成链表类的构造。
4. 链表类加法函数List Add(const List &list);
加法函数实现存储在链表中的两个大数相加。加法是从低位开始运算即从头节点head后一个结点开始进行运算,定义int型变量flag表示进位,初始值设置为0当两个链表中的结点相加超过10000,即一个结点中存储的数据超过四位flag更新为1,表示向下一个结点进一位。还需要考虑当两个大数的结点数不同的情况,结点数多的根据进位情况更改数值后直接接在新链表中。当两个链表都走到尾结点tail但flag仍为1则需要开辟新的结点将进位存入数据域data,并接在新链表的最后使其成为新链表的尾结点。
5. 链表类减法函数List Sub(const List &list);
减法函数实现存储在链表中的两个大数相减。减法是从低位开始运算即从头节点head后一个结点开始进行运算,定义int型变量flag表示借位,初始值设置为0,当两个链表中的结点相减小于0时则要加上10000,flag更新为-1表示向下一个结点借一位。也需要考虑当两个大数的结点数不同的情况,结点数多的根据借位情况更改数值后直接接在新链表中。若最后一个结点经过借位后数=数据域存储的数值变为0,则修改指针指向去掉该结点。小数减大数的情况,可在主函数中输出负号解决。
6. 链表类重载<=运算符bool operator <=(const List &list);
重载<=运算函数实现存