使用链表实现一元多项式的存储

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语言开辟结构体的空间,不了解结果体指针的使用等等,导致时间开销巨大(指完成代码),目前代码没有经过优化,仅能简单的实现基本操作的功能。

posted @ 2020-07-12 16:31  DNoSay  阅读(877)  评论(0编辑  收藏  举报