实验方案:
分别采用了顺序表、链表的方式实现一元多项式完成多项式的加、减运算并求值
1、实现功能描述:
(1) 输入和输出:
需要输入的信息有多项式的系数和指数,用来向系统动态申请内存;系数和指数用来构造每个结点,形成表。输入要求在程序运行过程中有提升,输出即对一元多项式进行遍历输出。
(2) 一元多项式的相加和相减:
多项式的加减要指数相同的同类项才能实现,所以需要在运行中对各种不同情况进行判断,最后得到的结果存到新的表中,形成一个新的多项式。
(3)已知自变量求一元多项式的值:
可以对输入的两个一元多项式及其经过加、减运算得到的新的一元多项式进行计算,只要给出x的值(可以为浮点数),即可求得三个多项式的结果。
2、方案比较与选择
(1) 从数据结构的逻辑结构与存储结构角度提供多种解决方案:
① 逻辑结构:
由于一元多项式是线性结构,所以我选择线性表来实现。线性表分为顺序表和链表两种:若一元多项式的每一项均的系数均不为0且项数确定的情况下(不讨论具体的操作),选择顺序表是个更好的解决方案;若一元多项式的项数在不确定的情况下(不讨论具体的操作),选择链表是个更好的解决的方案。
② 存储结构:
存储结构主要分为顺序存储方式、链式存储方式。若经常对一元多项式的某项进行操作且知道具体项数的情况,应选择顺序表;若不清楚对具体的哪一项进行操作的情况下,经常需要进行查找、插入、删除,则应选择链表。
(2) 从时空效率角度分析决定最终采用方案的原因。
① 若输入的一元多项式是项数固定且指数依次递增的系数非0项,在不需要经常进行插入、删除某一项的情况下,选择顺序表。即是因为在上述情形下无论采用顺序还是链式的存储方式,需要的空间都是一样,但是使用顺序表可以在操作上有效降低时间的复杂度。
② 若输入的一元多项式的项数不固定,且指数不是依次递增的式子,需要经常进行插入、删除的情况下,选择链表。即是因为在上述情形下每个结点代表一个项,多项式的每一项可以用其系数和指数唯一的表示,方便进行插入、删除等操作,在操作上有效降低空间的复杂度。
3、设计算法描述
(1)用简单示例结合所设计算法采用的数据逻辑结构图、存储结构图说明算法思想。
数据逻辑结构为:
顺序表和链表的逻辑结构均相同,先对需要存储输入一元多项式的表进行初始化,再输入多项式的项数和多项式的系数、指数,重复两次,再选择是否进行加\减运算,然后输入x的值,最后得到需要求的多项式的值。
数据存储结构:
顺序表的存储结构,是一个空间连续的表,通过下标来寻找数据元素,通过对数据的下标增加\减少来遍历整个表。
链式的存储结构,是一个线性的但空间不连续的表,通过头结点来访问链表,每一个结点具有数据域和指针域,通过指针域来存储下一个元素的地址,然后一个个地进行遍历。
(2)进行模块划分,给出功能组成框图。
功能主要分为初始化多项式、输入多项式、输出多项式、对多项式进行加\减、对多项式进行求值,通过主函数来调用各功能子函数来完成要求。
(3)用流程图描述关键算法。
关键算法:多项式的加、减运算。
顺序表中,先对两个多项式的第一项进行分析,若两项不相等,则先把小的一项放入新的表中,先放入一项的多项式下标加1用下一项和另一个多项式的第一项进行对比;若两项相等,则判断两项系数相加\减是否为0,若为0则两个多项式均自增到下一项进行比较;若不为0,则将得到的系数和表A的指数放入新的表中作为一项。如此循环对比,直到一个表到最后一项,然后再判断哪一个表不为空,将该表剩余的项均放入新的表中;若两个表刚刚好项数项数,则无需进行下一步。最后得到新的一元多项式。
链表中,先对两个多项式的第一项进行分析,若两项相等,则判断两项系数相加\减是否为0,若为0则两个多项式均自增到下一项进行比较;若不为0,则将得到的系数和表A的指数放入新的表中作为一项;若两项不相等,则先把小的一项放入新的表中,先放入一项的多项式下标加1用下一项和另一个多项式的第一项进行对比。如此循环对比,直到一个表到最后一项,然后再判断哪一个表不为空,将该表剩余的项均放入新的表中;若两个表刚刚好项数项数,则无需进行下一步。最后得到新的一元多项式。
4、算法实现(即完整源程序,带注解)
(1)顺序表的完整源代码:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<math.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
int num1, num2;
typedef struct
{
float coef; //系数
int exp; //指数
} Node;
typedef struct
{
Node *elem; //数据基地址
int length; //表的长度
} LinkList;
Status Initpolyn(LinkList *L, int n) //多项式的初始化
{
L->elem = (Node *)malloc(sizeof(Node) * n);
if (L->elem == NULL) //若空间申请失败,则返回0退出
return ERROR;
L->length = 0; //未输入前表的长度置为0
return OK;
}
void Inputpolyn(LinkList *La, int n) //输入系数和指数
{
int y, i;
float x;
printf("依次输入系数和指数(例:2*x^3输入为2,3):\n");
for (i=0; i<n; i++)
{
scanf("%f,%d", &x, &y); //x为系数,y为指数
La->elem[i].coef = x;
La->elem[i].exp = y;
La->length++; //完整输入一项后,表长度加1
}
}
void Outputpolyn(LinkList *L) //遍历输出多项式的内容
{
int i = 0;
for (i = 0; i < L->length; i++)
{
printf("%.2f x^%d | ", L->elem[i].coef, L->elem[i].exp);
}
}
Status addpolyn(LinkList *La, LinkList *Lb, LinkList *Lc, int n) //多项式加减运算
{
int i=0, j=0, k=0;