石家庄经济学院实验报告学院: 信息工程学院专业: 计算机科学技术计算机人论坛1.需求分析1.1开发背景在现实生活中不可避免地我们会遇到一些超大整数之间的运算,比如要计算马云的资产,以及国有银行的转账收入支出等一些数的存储等等类似的问题,而由于计算机整形数的最小值和最大值范围仅为-32768到32767,所以关于大整数的实验即呼之欲出,本实验就是针对数值很大、精度很高的大整数进行的加法减法以及乘法的计算。
1.2数据需求指针:L1,L2:分别为指向这两条存储要进行运算的链表头结点的指针;L3:指向乘法的结果链表;L4:在运算乘法的时候做中间量使用。
prior:双向链表的头指针;next:双向链表的尾指针。
data:整形数,链表所存的数据。
1.3功能需求对一个进行运算的软件,加法和减法是最基本的运算,本实验又额外增加了大整数的乘法。
1.4测试数据第一个数:9,568,974,512;第二个数:8,648,761,512;2.概要设计2.1功能模块图由需求分析可画出如下功能模块图。
图2-1 功能模块图2.2各功能子程序定义1.创建链表:Status creat(DuLinkList &L,char str[30]);2.输出链表中结点内的数据:Status output(DuLinkList L);3.加法:DulNode *Add(DuLinkList L1,DuLinkList L2);4.减法:DulNode *Sub(DuLinkList L1,DuLinkList L2);5.乘法:DulNode *Mul(DuLinkList L1,DuLinkList L2);计算机人论坛2.3主界面截图图2-3 程序主界面3.详细设计3.1数据结构设计此款软件是基于线性表双向链表完成的,在每个分过程中都充分利用了链表指针灵活又不太易于掌控的特性,但若是全面理解指针以及链表的特点,也是很容易设计此款软件的。
在大整数加减乘法软件中主要有以下几种数据(1)Status, ElemType都是宏定义的整形量;(2)DulNode是结构体,包含三个域,data,prior,next,分别是整形数,左指针,右指针;3.2模块详细设计由于加法和减法的操作易于实现,在此并不一一赘述。
乘法的实现:(1)构思:本函数又另设一个指针L3和L4,L3用于存储每一层的乘法结果,L4则每次都加上L3链表,直至结束,最后L4指向的链表即为乘法的结果。
(2)一级算法:P1和p2分别指向L1和L2结点的下一个结点遍历L1和L2,分别计算两链表的长度若L2长于L1,则分别交换L1和L2,p1和p2。
新建结点L3和L4,p3和q分别指向L3指向的结点。
Do{计算L3链表}为L3加上头结点;把L3赋给L4;P1重新置于L1尾部,p2前移一位;Do{重新做一条L3链;Do{计算L3链}当p1->next为NULLW指向L3链尾;把L3加到L4上;}当p2->prior为空返回L4;(3)二级求精:L3->data = 上一位的进位加上L1结点加上L2结点;计算Prov;新建L3->prior;计算L3结点数据;P1前移计算机人论坛3.3测试与运行本程序是用C语言在VisualC++环境编译所完成,经部分数据验证无误,现将测试与运行结果展示如下:(1)加法:图3-3-1 加法(2)减法和乘法:图3-3-2 减法和乘法(3)输入:图3-3-3 输入计算机人论坛4.总结与展望《数据结构》果然不是闹着玩的,要想学好,必须得下苦功夫!!!5.参考文献[1].严蔚敏.数据结构[M].北京:清华大学出版社,2013。
计算机人论坛6.源代码清单#include<stdio.h>#include<stdlib.h>#include"max_tou.h"Status input(LinkList &p){LinkList head,s;int v;int tamp;tamp=0;head=(LinkList)malloc(sizeof(LNode));p=head;while(tamp==0) /*创建n个元素的双向链表*/{scanf("%d",&v); /*束三个三个输入*/if (v>=0){s=(LinkList)malloc(sizeof(LNode));s->data=v; /*赋值*/p->next=s; /*连接*/s->prior=p;p=s;}elsetamp=1; /*为负数时结束*/ }head=head->next; /*去掉头节点*/head->prior=NULL; /*让双向链表前后都为空*/p->next=NULL;return OK;}Status output(LinkList &p,LinkList &head) /*输出*/{LinkList s;s=head;while(s!=NULL){if(s->data>=100) printf("%d",&s->data);if(s->data>=10 && s->data<100) printf("0%d",&s->data);if(s->data>0 && s->data<10) printf("00%d",&s->data);s=s->next;}return OK;}Status max_add(LinkList &head1,LinkList &head2,LinkList &p1,LinkList&p2) /*链表加法*/{LinkList p,q;int n=0,m=0;p=head1;q=head2;while(p!=NULL) /*遍历链表然后记录链表长度*/{n=n+1;p=p->next;}while(q!=NULL) /*遍历链表然后记录链表长度*/{m=m+1;q=q->next;}p=p->prior;q=q->prior;if(n>=m) /*当head1 大于head2时*/{while(q!=NULL){p->data=p->data+q->data; /*两个链表相加直到其中一个走完或者全都走完结束*/if(p->data>=1000){p->prior->data=p->prior->data+1;p->data=p->data%1000;}p=p->prior;q=q->prior;}while(p!=NULL) /*当出现进位但是前面却为空时需要申请一个空间然后放进去进的位数*/{if(p->data>=1000){if(p->prior==NULL){q=(LinkList)malloc(sizeof(LNode));q->data=1;p->prior=q;q->next=p;q->prior=NULL;p=NULL;}else{p->prior->data=p->prior->data+1;p->data=p->data%1000;p=p->prior;}}}output(head1,p1);}if(n<m){while(p!=NULL){q->data=q->data+p->data;if(q->data>=1000){q->prior->data=q->prior->data+1;q->data=q->data%1000;}p=p->prior;q=q->prior;}while(q!=NULL){if(q->data>=1000){if(q->prior==NULL){p=(LinkList)malloc(sizeof(LNode));p->data=1;q->prior=q;p->next=p;p->prior=NULL;q=NULL;}else{q->prior->data=q->prior->data+1;计算机人论坛q->data=q->data%1000;q=q->prior;}}}output(head2,p2);}return OK;}Status max_sub(LinkList &head1,LinkList &head2,LinkList &p1,LinkList &p2) /*链表减法*/{LinkList p,q;int n=0,m=0;p=head1;q=head2;while(p!=NULL) /*遍历链表然后记录链表长度*/{n=n+1;p=p->next;}while(q!=NULL) /*遍历链表然后记录链表长度*/{m=m+1;q=q->next;}p=p->prior;q=q->prior;if(n>=m) /*当head1 大于head2时*/{while(q!=NULL){p->data=p->data-q->data; /*两个链表相加直到其中一个走完或者全都走完结束*/if(p->data<0){p->prior->data=p->prior->data-1;p->data=p->data+1000;}p=p->prior;q=q->prior;}output(head1,p1);}if(n<m){while(p!=NULL){q->data=q->data-p->data;if(q->data<0){q->prior->data=q->prior->data-1;q->data=q->data+1000;}p=p->prior;q=q->prior;}output(head2,p2);}return OK;}Status max_mul(LinkList &head1,LinkList &head2,LinkList &p1,LinkList &p2,LinkList &L) /*链表乘法*/{LinkList s;LinkList b,d;LinkList p,q;LinkList h1,h2,tail1,tail2;int n=0,m=0;int i;LinkList r,tail,tailr;ElemType mo,di,re,edi;int c,flag ;p=head1;q=head2;while(p!=NULL) /*遍历链表然后记录链表长度*/{n=n+1;p=p->next;}while(q!=NULL) /*遍历链表然后记录链表长度*/{m=m+1;q=q->next;}h1=(LinkList)malloc(sizeof(LNode)); /*要装拆分第一个双向链表后的链表*/tail1=h1;h1->prior=NULL;i=0;while(i<(3*n)){p=(LinkList)malloc(sizeof(LNode));p=tail1->next;tail1=p->prior;tail1=p;i=i+1;}tail1->next=NULL;h2=(LinkList)malloc(sizeof(LNode)); /*要装拆分第二个双向链表后的链表*/tail2=h2;h2->prior=NULL;i=0;while(i<(3*m)){q=(LinkList)malloc(sizeof(LNode));q=tail2->next;tail2=q->prior;tail2=q;i=i+1;}tail2->next=NULL;s=head1;b=h1->next;while(s!=NULL){b->data=s->data/100; /*拆分head1链表然后放进刚刚建立好的h1双向链表中*/b=b->next;b->data=s->data/10%10;b=b->next;b->data=s->data%10;b=b->next;s=s->next;}s=head2;d=h2->next;while(s!=NULL){d->data=s->data/100; /*拆分head2链表然后放进刚刚建立好的h2双向链表中*/d=d->next;d->data=s->data/10%10;d=d->next;d->data=s->data%10;d=d->next;s=s->next;}/*要做p q 两个链表相乘要考虑进位还有将所得结果放到哪个链表中等问题*/L = (LinkList)malloc(sizeof(LNode)) ; /*用L来装乘完后的数据*/if(!L)exit(OVERFLOW);L->next = NULL;L->prior = NULL;di = 0;edi = 0;tail = p;while(p != NULL){re = p->data * q->data;mo = re % 10;if(L->prior == NULL) {r = L;r->data = mo + di;if (r->data >= 10){edi = r->data / 10;r->data = r->data % 10;}else {edi = 0;}L->prior = L;}else {r = (LinkList)malloc(sizeof(LNode));r->data = mo + di;if (r->data >= 10){edi = r->data / 10;r->data = r->data % 10;}else {edi = 0;}L->prior = r;r->next = L;L = r;}di = edi + re / 10;edi = 0;p = p->prior;}while(di > 0){r = (LinkList)malloc(sizeof(LNode)); r->data = di % 10;di = di / 10;L->prior = r;r->next = L;L = r;L->prior = NULL;}L->prior = NULL;while (r->next != NULL) r = r->next; tailr = r;c=1;q = q->prior;while (q != NULL){p = tail;r = tailr;flag = 0;di = 0;edi = 0;for(i=1;i<=c;i++){if(r->prior != NULL)r = r->prior;else {r = (LinkList)malloc(sizeof(LNode));r->data = 0;L->prior = r;r->next = L;L = r;L->prior = NULL;flag = 1;}}while(p != NULL){re = p->data * q->data;mo = re % 10;if(flag == 0) r->data = r->data+ mo + di;else r->data = mo + di;if (r->data >= 10){edi = r->data / 10;r->data = r->data % 10;}di = edi + re / 10;edi = 0;p = p->prior;if(r->prior != NULL)r = r->prior;else {r = (LinkList)malloc(sizeof(LNode));r->data = 0;L->prior = r;r->next = L;L = r;L->prior = NULL;flag = 1;}}if(di > 0){r->data = di % 10;di = di / 10;}q =q->prior;c++;}return OK;}Status main(){int choose,i;LinkList head1,head2,p1,p2,L;choose=0;while (choose==0){printf("1 输入大整数\n");printf("2 输出大整数\n");printf("3 大整数之和\n");printf("4 大整数之差\n");printf("5 大整数之机\n");printf("6 退出\n");scanf("%d",&choose);switch (choose){case 1:printf("请输入第一个大整数以负数代表结束\n");input(head1);printf("请输入第二个大整数以负数代表结束\n");input(head2);break;case 2:printf("第一个大整数为\n");output(head1,p1);printf("第二个大整数为\n");output(head2,p2);break;case 3:printf("两个大整数相加后结果为\n");max_add(head1,head2,p1,p2);break;case 4:printf("两个大整数相减后结果为\n");max_sub(head1,head2,p1,p2);break;case 5:printf("两个大整数相乘后结果为\n");max_mul(head1,head2,p1,p2,L);break;case 6:choose=1;break;}}return(0);}计算机人论坛。