使用链表实现一元多项式的存储
ADT(Abstract Data Type, 抽象数据类型)
ADT LinkedUnaryPoly{
数据对象:D = {p1, p2, ..., pn, e1, e2, ...,en| pi(-R, ei(-N, i(-N}
数据关系:R = {<Item1(p1,e1), Item2(p2,e2), ..., Itemn(pn,en)>| Item1是一元多项式的系数为p1且次数为e1的项,
Item2是一元多项式系数为p2且次数为e2的项, ..., Itemn是一元多项式系数为pn且次数为en的项, P是包含有n个系数不为零的项的一元多项式}
基本操作:
create(&P, Item1, Item2, ..., Itemn)
初始条件:Item1, Item2, Itemn均为系数不为零的一元多项式的项,且按照次数由小到大出现
操作结构:构造包含n个系数不为零的项的一元多项式P
calculate(&ans, P, x)
初始条件:P是一元多项式, x是实数
操作结构:确定P的元,计算一元多项式的值并返回
add(&P, P1, P2)
初始条件:P1, P2是一元多项式
操作结果:返回P1, P2的和
sub(&P, P1, P2)
初始条件:P1, P2是一元多项式
操作结果:返回P1, P2的差
}ADT LinkedUnaryPoly;
定义存储结构
/** * 使用链表实现线性表存储一元多项式的定义 */ /** * 定义一元多项式系数不为零的项 */ typedef struct Item { double p; int e; Item *next; } Item;
定义基本操作
/** * 定义基本操作 */ /** * 构造一元多项式 * @param p 一元多项式的系数数组 * @param e 一元多项式的次数数组 * @return 一元多项式的头结点 */ Item *create(double p[], int e[],int len) { //定义一元多项式链表的头结点,令头结点指向的下一项为空 Item* head = new Item; head->next = NULL; //遍历系数数组和次数数组,构造一元多项式 int i = 0; //定义指针记录一元多项式链表的最后一个结点的位置 Item *tail = head; while (i < len) { if(p[i]-0 <= 1e-9){ continue; } Item *item = new Item; //有新的结点加入,让新加入的结点作为上一个结点(尾结点)的后继并让当前结点作为新的尾结点 tail->next = item; tail = item; item->p = p[i]; item->e = e[i]; item->next = NULL; //如果头结点指向的下一个项为空,将当前项作为多项式的第一项和最后一项 if (head->next == NULL) { head->next = item; tail = item; } i++; } return head; } /** * 计算给定自变量x下,一元多项式的值 * @param head 一元多项式的头结点 * @param x 自变量x * @return 一元多项式的值 */ double calculate(Item* head, double x) { double ans = 0; //定义变量存储临时结点 Item *temp = head; while (temp->next != NULL) { temp = temp->next; ans += pow(x, temp->e) * temp->p; } return ans; } /** * 计算两个一元多项式之和 * @param head1 一元多项式1的头结点指针 * @param head2 一元多项式2的头结点指针 * @return 两个一元多项式之和的一元多项式的头结点指针 */ Item* add(Item *head1, Item *head2) { //定义两个临时指针变量存储当前遍历到的两个链表结点的指针 Item *temp1 = head1; Item *temp2 = head2; //定义头尾结点 Item *head = new Item; head->next = NULL; Item *tail; while (temp1->next != NULL && temp2->next != NULL) { //创建一个新的结点 Item *i = new Item; if (temp1->next->e == temp2->next->e) { //如果两链表下一结点的项次数相同,让新结点系数为两链表下一结点项的系数之和,次数为两链表下一结点项的次数,并使指向两链表下一结点的指针分别指向下一结点 i->p = temp1->next->p + temp2->next->p; i->e = temp1->next->e; i->next = NULL; temp1 = temp1->next; temp2 = temp2->next; } else if (temp1->next->e < temp2->next->e) { //如果两链表下一结点的项次数不同,让新结点其和两链表中下一结点次数小的结点项一致,并让指向下一结点项次数小的链表的当前结点指向该链表下一结点 i->p = temp1->next->p; i->e = temp1->next->e; i->next = NULL; temp1 = temp1->next; } else{ //如果两链表下一结点的项次数不同,让新结点其和两链表中下一结点次数小的结点项一致,并让指向下一结点项次数小的链表的当前结点指向该链表下一结点 i->p = temp2->next->p; i->e = temp2->next->e; i->next = NULL; temp1 = temp2->next; } //如果头结点指向的下一结点为空,让新结点成为头结点指向的下一结点和尾结点 if(head->next == NULL){ head->next = i; tail = i; } //将新创建的结点成为新的尾结点 tail->next = i; tail = i; } while (temp1->next !=NULL) { //如果一元多项式1还未遍历完,遍历一元多项式1剩余项,将剩余项逐一添加到欲返回的一元多项式后 //创建一个新的结点 Item *i = new Item; i->p = temp1->next->p; i->e = temp1->next->e; i->next = NULL; temp1 = temp1->next; //将新创建的结点成为新的尾结点 tail->next = i; tail = i; } while (temp2->next !=NULL) { //如果一元多项式2还未遍历完,遍历一元多项式2剩余项,将剩余项逐一添加到欲返回的一元多项式后 //创建一个新的结点 Item *i = new Item; i->p = temp2->next->p; i->e = temp2->next->e; i->next = NULL; temp2 = temp2->next; //将新创建的结点成为新的尾结点 tail->next = i; tail = i; } return head; } /** * 计算两个一元多项式之差 * @param head1 被减一元多项式的头结点指针 * @param head2 减一元多项式的头结点指针 * @return 两个一元多项式之差的一元多项式的头结点指针 */ Item* sub(Item *head1, Item *head2) { //定义两个临时指针变量存储当前遍历到的两个链表结点的指针 Item *temp1 = head1; Item *temp2 = head2; //定义头尾结点 Item *head = new Item; Item *tail; while (temp1->next != NULL) { //创建一个新的结点 Item *i = new Item; if (temp1->next->e == temp2->next->e) { //如果两链表下一结点的项次数相同,让新结点系数为两链表下一结点项的系数之差,次数为两链表下一结点项的次数,并使指向两链表下一结点的指针分别指向下一结点 i->p = temp1->next->p - temp2->next->p; i->e = temp1->next->e; i->next = NULL; temp1 = temp1->next; temp2 = temp2->next; } else if (temp1->next->e > temp2->next->e) { //如果被减多项式的下一项次数大于减多项式的下一项次数,让新结点的系数为减多项式下一项系数的相反数,次数为减多项式的下一项次数,指向减多项式当前项的指针指向下一项 i->p = -temp2->next->p; i->e = temp2->next->e; i->next = NULL; temp2 = temp2->next; } else{ //如果被减多项式下一项的次数大于减多项式下一项次数, 将被减多项式的下一项添加到欲返回的多项式的尾部 i->p = temp1->next->p; i->e = temp1->next->e; i->next = NULL; //指向被减多项式的当前项指针后移,指向下一项并终止本次循环 temp1 = temp1->next; } //如果头结点指向的下一结点为空,让新结点成为头结点指向的下一结点和尾结点 if(head->next == NULL){ head->next = i; tail = i; } //将新创建的结点成为新的尾结点 tail->next = i; tail = i; } while (temp2->next !=NULL) { //如果一元多项式2还未遍历完,遍历一元多项式2剩余项,将剩余项系数取相反数后逐一添加到欲返回的一元多项式后 //创建一个新的结点 Item *i = new Item; i->p = -temp2->next->p; i->e = temp2->next->e; i->next = NULL; temp2 = temp2->next; //将新创建的结点成为新的尾结点 tail->next = i; tail = i; } return head; }
测试数据结构
int main() { double p1[]={1,1,1}; int e1[]={0,1,2}; double p2[]={1,1,1}; int e2[]={1,2,3}; Item* poly1 = create(p1,e1,sizeof(p1)/sizeof(p1[0])); printf("%lf\n", calculate(poly1, 2)); Item* poly2 = create(p2,e2,sizeof(p2)/sizeof(p2[0])); printf("%lf\n", calculate(poly2, 2)); Item* poly = sub(poly1,poly2); Item * temp = poly; printf("%lf\n", calculate(poly,2)); return 0; }
输出结果
自己在实现基本操作过程中发现了很多不足,不会使用C语言开辟结构体的空间,不了解结果体指针的使用等等,导致时间开销巨大(指完成代码),目前代码没有经过优化,仅能简单的实现基本操作的功能。
路漫漫其修远兮,吾将上下而求索。