zoukankan      html  css  js  c++  java
  • 【Weiss】【第03章】练习3.7:有序多项式相乘

    【练习3.7】

    编写一个函数将两个多项式相乘,用一个链表实现。你必须保证输出的多项式按幂次排列,并且任意幂次最多只有一项。

    a.给出以O(M2N2)时间求解该问题的算法。

    b.写一个以O(M2N)时间执行乘法的程序,其中M≤N。

    c.写一个以O(MNlog(MN))时间执行乘法的程序。

    d.上面哪个时间界最好?

    Answer:

    【a】.将两链表元素两两相乘并列出,从第一项开始,依次与其后的所有项比较,如相等则合并。

    合并完成后,每次找出幂次最小的项,插入链表。(最原始的方法)

    【b】.M≤1时,方法易知。

    M≥2时,每次将长度为M的链表的一项,与另一链表的所有项相乘,每次一组N个有序的多项式元素。

    对于每两组上式的N个多项式元素,基本按练习3.5有序链表求并的算法(除幂次相同需将系数相加)操作。

    求并算法时间复杂度O(M+N),故该算法复杂度为

    (乘法时间)O(MN)+(求并时间)O((N+N)+(2N+N)+(3N+N)+……+(MN+N))=O(M2N)

    【详情见代码】

    【c】.同a先将两链表元素两两相乘并列出,对MN项元素进行O(NlogN)的排序

    排序完成后,遍历代码,合并同幂次项,最后全部插入链表。时间复杂度为:

    (乘法时间)O(MN)+(排序时间)O(MNlogMN)+(合并同类项时间)O(MN)=O(MNlogMN)

    【详见代码】

    代码部分,首先是测试代码,b和c的测试代码写在一起了

     1 #include <iostream>
     2 #include "linklist.h"
     3 using linklist::List;
     4 using namespace std;
     5 int main(void)
     6 {
     7     //测试多项式加法
     8     List<Poly> a;
     9     a.additem(Poly(3, 1));
    10     a.additem(Poly(1, 2));
    11     a.additem(Poly(4, 3));
    12     a.additem(Poly(7, 4));
    13     a.additem(Poly(2, 5));
    14     cout << "  ( " << flush;
    15     a.traverse();
    16     cout << ")  +
    " << flush;
    17     List<Poly> b;
    18     b.additem(Poly(5, 2));
    19     b.additem(Poly(2, 3));
    20     b.additem(Poly(1, 5));
    21     b.additem(Poly(3, 7));
    22     b.additem(Poly(1, 11));
    23     cout << "  ( " << flush;
    24     b.traverse();
    25     cout << ") =
    " << flush;
    26 
    27     List<Poly> answer = linklist::polymulti_seq(a, b);
    28     List<Poly> another = linklist::polymulti_sort(a, b);
    29     cout << "
      ( " << flush;
    30     answer.traverse();
    31     cout << ") 
    " << flush;
    32 
    33     cout << "
      ( " << flush;
    34     another.traverse();
    35     cout << ") 
    " << flush;
    36     system("pause");
    37 }
    View Code

    实现部分,首先需在poly.h中重载多项式元素的乘法运算符

    1 //练习3.7新增,多项式元素乘法*
    2 Poly operator*(const Poly& poly1, const Poly& poly2)
    3 {
    4     Poly answer;
    5     answer.coefficient = poly1.coefficient*poly2.coefficient;
    6     answer.exponent = poly1.exponent + poly2.exponent;
    7     return answer;
    8 }

    然后是小题b代码,包括习题3.5求并成员函数的模板特例化的辅助函数及主相乘算法

     1 //练习3.7b新增,将3.5求并的成员函数特例化
     2 template <> void List<Poly>::join(List<Poly> inorder)
     3 {
     4     Node<Poly>* curr = front;
     5     Node<Poly>* prev = nullptr;
     6     Node<Poly>* curr2 = inorder.front;
     7     while (curr != nullptr && curr2 != nullptr)
     8     {
     9         if (curr->data < curr2->data)
    10         {
    11             prev = curr;
    12             curr = curr->next;
    13         }
    14         else if (curr2->data < curr->data)
    15         {
    16             additem(curr2->data, prev);
    17             if (prev == nullptr)
    18                 prev = front;
    19             else
    20                 prev = prev->next;
    21             curr2 = curr2->next;
    22         }
    23         else
    24         {
    25             //对比3.5唯一增加语句
    26             //当两元素幂次相等时,原链表与新链表的多项式系数相加并将指针后移
    27             curr->data = curr->data + curr2->data;
    28             prev = curr;
    29             curr = curr->next;
    30             curr2 = curr2->next;
    31         }
    32     }
    33     while (curr2 != nullptr)
    34     {
    35         additem(curr2->data, prev);
    36         if (prev == nullptr)
    37             prev = front;
    38         else
    39             prev = prev->next;
    40         curr2 = curr2->next;
    41     }
    42 }
    43 
    44 //练习3.7b新增,以O(M²N)时间执行多项式乘法
    45 List<Poly> polymulti_seq(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
    46 {
    47     //保证首链表长度较小
    48     if (inorder_a.size() > inorder_b.size())
    49         return polymulti_seq(inorder_b, inorder_a);
    50     else
    51     {    
    52         List<Poly> answer;
    53         for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
    54         {
    55             //用较短链表中每一个元素乘较长链表,得到临时链表
    56             {
    57                 List<Poly> temp;
    58                 for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
    59                     temp.additem(iter_a->data * iter_b->data);
    60                 answer.join(temp);
    61             }
    62         }
    63         return answer;
    64     }
    65 }

    然后为c小题算法,调用了标准库中的快排,需要#include<algorithm>

     1 //练习3.7c新增,以O(MNlogMN)时间执行多项式乘法
     2 List<Poly> polymulti_sort(const List<Poly> &inorder_a, const List<Poly> &inorder_b)
     3 {
     4     unsigned maxsize = inorder_a.size() * inorder_b.size();
     5     //申请M*N大小的数组
     6     Poly* temp_array = new Poly[maxsize];
     7     unsigned int index = 0;
     8     //依次对链表每两个节点元素相乘并放在数组中
     9     for (Node<Poly>* iter_a = inorder_a.begin(); iter_a != nullptr; iter_a = iter_a->next)
    10         for (Node<Poly>* iter_b = inorder_b.begin(); iter_b != nullptr; iter_b = iter_b->next)
    11             temp_array[index++] = iter_a->data*iter_b->data;
    12     //对数组进行升序快排
    13     sort(&temp_array[0], &temp_array[--index]);
    14     List<Poly> answer;
    15     //单次遍历数组,合并同类项
    16     for (index = 1; index < maxsize; ++index)
    17     {
    18         if (temp_array[index] == temp_array[index - 1])
    19             temp_array[index] = temp_array[index - 1] + temp_array[index];
    20         else
    21             answer.additem(temp_array[index - 1]);
    22     }
    23     answer.additem(temp_array[index - 1]);
    24     delete[] temp_array;
    25     return answer;
    26 }
  • 相关阅读:
    [破解] nasca drm file -ver1.00
    [KEY] DK NOTES
    [Java] Tomcat环境变量设置
    [Java] Java record
    [SQL] SQL Server 触发器
    [GitHub] GitHub Repositories
    [GitHub] GitHub使用教程for Eclipse
    [SharePoint] SharePoint 错误集 3
    [SharePoint] SharePoint 错误集 2
    [SharePoint] SharePoint 错误集 1
  • 原文地址:https://www.cnblogs.com/catnip/p/4331347.html
Copyright © 2011-2022 走看看