一个野生程序猿的折腾日记

数据结构实验(1)-线性表的应用

一元多项式

实验报告

线性表的应用:稀疏一元多项式运算器

1.问题的描述

一元多项式在存储与运行的时候,一种常见的存储方法是根据最高项的幂次,按顺序生成数组。然而,当多项式比较稀疏的时候,大多数的存储空间被浪费在存储0系数的项中。因此,本实验采用链表的形式对多项式进行存储和运算,在节省空间的同时提高运算效率。

2.算法的描述

(1)数据结构的描述

本实验主要使用到了poly结构体,其定义如下:

struct poly
{
    float coef;
    int expn;
    struct poly *next;
};

其中,coef是每个项的系数,expn是幂次,next为指向下一个poly的指针。

另外,在主函数中,本文主要使用到了结构体数组polyns,其定义如下:

struct poly polyns[5];

本文的思想是,生成结构体数组,里面分别储存

  • 主多项式
  • 次多项式
  • 求和结果
  • 微分结果
  • 不定积分结果

在使用的时候,主要使用该数组的指针,传入给对应的函数进行操作。

(2)程序结构的描述

        函数原型、功能和接口的描述。

本实验主要定义如下函数,其原型为:

void intro();
status create(poly);
void show(struct poly);
int menu();
status add(poly, poly, poly);
status diff(poly, poly);
status integral(poly, poly);
status hasExpn(struct poly, int);
status insert(poly, poly);

下面将分别介绍各个函数的功能和接口

  • void intro();

该函数用于展示程序一开始的页面,以及使用说明,保证程序对使用人友好

  • status create(struct poly *polyn);

该函数用于创建多项式,传入参数的为头节点指针,返回的参数为创建的status,如果创建成功则返回OK;

在本函数中,将接受用户的输入,分配空间并展示创建结果。

  • status hasExpn(struct poly polyn, int expn)

本函数用于遍历一个链表,查看该链表中是否已经存在幂次为expn的项,如果有则返回TRUE,没有则返回FALSE。

  • status insert(struct poly *polyn, struct poly *new_poly)

本函数用于将一个新的项插入已有的多项式链表,根据题目要求,采用递减顺序插入。

  • void show(struct poly polyn)

本函数用于展示多项式,传入参数为一个多项式链表的头节点指针。

本函数针对微分可能出现的一些问题进行了深度优化,从而保证每种情况下都可以得到准确的结果。

  • int menu()

本函数用于展示菜单,方便用户进行选择

  • status add(struct poly *add1, struct poly *add2, struct poly *sum)

本函数用于实现多项式的相加。在使用本功能时,需要先创建一个新的多项式,求和的结果的头节点储存在结构体指针sum中。

  • status diff(struct poly *raw, struct poly *diff_res)

本函数用于实现微分,通过用户输入次数来确定微分的次数,支持0次项消除

  • status integral(struct poly *raw, struct poly *int_res)

本函数用于实现不定积分,结果的头节点储存在结构体指针int_res中。

3.调试分析

        测试数据的选择,程序调试中遇到的问题及解决方法。

本实验采用题中给定的例子数据进行测试,在测试过程中遇到了各种各样的问题,问题描述与解决办法如下:

  • Q:在做加法的时候,是否采用课上学的就地归并法
    • A:由于接下来还要实现微分和积分,需要保持主多项式不变,所以每次都会生成新的空间进行存储,而不是改变原有的链接。
  • Q:在做微分的时候,如何实现高阶微分
    • A:采用循环方法,每次做完之后,把微分的结果作为下一次微分的初始值,进行下一次微分
  • Q:在进行微分结果的输出时,如何消除0项
    • A:由于低次函数在微分几次之后就会变成0,所以在show()函数中何时输出+号,输出在数字前方还是后方就很麻烦。本实验采用多个判断语句,考虑了是否全部系数都为0、系数是否为0;是否为倒数第一项、是否为倒数第二项、指数是否为0等多种特殊情况,最终使得结果变得合理且符合常识。

4.算法的时空分析

  • 时间复杂度
    • 创建:本实验在创建的时候就是按照非递减顺序排列,因此存在一个一边比较一边插入的情况,因此复杂度为O(Length),其中Length为链表长度、
    • 相加:在这里主要是遍历两个链表产生的时间复杂度,复杂度为O(Length 1+ Length 2)。
    • 微分:在这里主要是遍历一个链表产生的时间复杂度+高阶微分产生的循环复杂度,复杂度为O(N*Length),N为微分次数
    • 不定积分:在这里主要是遍历一个链表产生的时间复杂度,复杂度为O(Length)。
  • 空间复杂度
    • 创建:生成一个链表,每个链表的长度为Length,所占空间为Length * (sizeof(float) + sizeof(int) + sizeof(poly))
    • 相加:生成一个新的链表,长度为Length 1+ Length 2,所占空间为:(Length 1+ Length 2)* (sizeof(float) + sizeof(int) + sizeof(poly))
    • 微分、不定积分:都是生成一个跟原始链表长度一样的新链表,所占空间为:Length * (sizeof(float) + sizeof(int) + sizeof(poly))

5.测试结果及分析

        列出测试数据和测试结果,给出分析和说明。

(1)创建

这里使用题目中给出的例子进行创建:

X3+3X2+2X+6    X3-X2+2X-2

健壮性:

可以看出,产生的结果与输入顺序无关

(2)求和

采用题中所给的例子,求X3+3X2+2X+6与X3-X2+2X-2的和

可以看出,其和为2X3+2X2+4X+4,正确

健壮性:

可以看出,本代码可以把系数为0项消除,即实现:(X3+3X2+2X+6) + (X3-3X2+2X+6)=2X3+4X+12

(3)微分

采用题中例子,求X3+3X2+2X+6的1阶和2阶微分

可以看出,微分结果正确

健壮性:

可以看出,高阶微分完之后输出为0,与题目相符

(4)不定积分

采用题中例子,求X3+3X2+2X+6的不定积分

可以看出,不定积分计算正确。有几个系数看起来比较奇怪,是为了美观,对系数进行了保留一位小数的处理。

6.实验体会和收获

经过本次实验,我提高了对结构体指针的认识,在实践中实现了链表的各种运算,了解了类C语言和C语言的一些差别。

Pages: 1 2 3

Warning: printf(): Too few arguments in /www/wwwroot/www.xiaoyaojiushao.com/wp-content/themes/simple-flat/inc/template-tags.php on line 58

发表评论

邮箱地址不会被公开。 必填项已用*标注