【问题标题】:simplifying terms in a polynomial by c++用c ++简化多项式中的项
【发布时间】:2017-01-30 16:44:24
【问题描述】:

我正在尝试编写一个函数来简化多项式中的项:

假设我们可以用一个双成员整数数组来表示每个项,其中第一个成员显示变量,第二个成员是系数。例如 4a3b 可以分别表示为 (1, 4) 和 (2, 3)。在这些示例中,我们根据字母顺序 (a:1, b:2, c:3, ...) 通过整数显示变量 (a, b, ..)。

因此,多项式可以表示为这些项的向量。例如 4a+2b+10c 可以显示为 {(1,4), (2,2), (3,10)}。 现在,目标是简化多项式。例如:

2a+3c-a+5t-3c = a+5t
我已经用 C++ 编写了一个代码来完成这项工作,但是对于大型多项式来说它非常慢。

void simplify (vector<int*> &p)
{
    vector<int*>:: iterator it1 = p.begin();
    vector<int*>:: iterator it2;
    while (it1!=p.end())
    {
        if ((*it1)[1]!=0) // if the coefficient is not equal to zero
        {
            it2 = it1+1;
            while (it2!=p.end())
            {
                if ((*it1)[0]==(*it2)[0]) //if the variables are similar
                {
                    (*it1)[1] += (*it2)[1];
                    (*it2)[1]=0; //set the coefficient equal to zero 
                }
                it2++;
            }
        }
        it1++;
    }
    it1 = p.begin();
    while (it1!=p.end()) //removing the terms with zero coefficient
    {
        if ((*it1)[1]==0)
            it1 = p.erase (it1);
        else
            it1++;  
    }
}

感谢所有可以向我展示代码问题以及如何提高代码速度的人。

【问题讨论】:

  • 我很想听听使用vector&lt;int*&gt; 而不是vector&lt;int&gt; 的解释。 -- 但是对于大型多项式来说它非常慢。 -- 您正在运行发布、优化的构建,还是“调试”、未优化的构建?如果它是一个调试/未优化的构建,那么你得到的任何时间都是没有意义的。
  • 此外,要从符合条件的容器中删除项目,无需编写循环。 p.erase(std::remove_if(p.begin(), p.end(), [](auto val) { return *val == 0; }), p.end());
  • 其实这个函数是我原来函数的简化版,因为它是一个有很多类的大型项目的一部分。所以我只是试图展示算法并找出它可能存在的问题。
  • 另外,你如何表示负系数?例如:4a - 5b。这是 (1, 4), (2, -5) 吗?如果是这样,那么这不是一个非常困难的任务,并且比您发布的要简单得多。您只需对第一个成员进行排序,然后为相同的排序成员添加第二个成员。此外,std::vector&lt;std::pair&lt;int, int&gt;&gt;std::vector&lt;int *&gt; 更有意义。
  • 感谢您的提示。我的另一个问题是,在这种情况下使用向量、列表或其他容器有什么区别。

标签: c++ vector iterator traversal


【解决方案1】:

您的代码中肯定有一些内容可以更改。但由于您主要关心的是效率,因此我建议您采取的第一个行动是使用不同的算法。

您当前的算法会检查每个元素的向量的剩余部分,寻找相同的符号并添加您找到的符号以获得最终系数。因此你的算法是;

for i in range(0, p.size()):
    for j in range(i+1, p.size()):
        // do the processing

您可能已经注意到,此算法的复杂度为 O(N2),这是您的代码效率低下的主要原因。

作为替代方案,您可以只遍历向量并将值放入 std::set。 (假设 STL 不是禁区,考虑到您对 std::vector 的使用)下面是我的想法的粗略实现,基于您的代码。

void simplify (vector<int*> &p)
{
    vector<int*>::iterator it1 = p.begin();
    vector<int*>::iterator it2 = p.end();
    map<int, int> m;
    map<int, int>::iterator itMap1, itMap2;
    while (it1!=it2)
    {
        if(m.find((*it1)[0]) != m.end())
        {
            m[(*it1)[0]] += (*it1)[1];
        }
        else
        {
            m[(*it1)[0]] = (*it1)[1];
        }
        it1++;
    }
    itMap = m.begin();
    itMap2 = m.end();
    p.resize(m.size());
    it = p.begin();
    while (itMap!=itMap2)
    {
        (*it1)[0] = itMap->first;
        (*it1)[1] = itMap->second;
        itMap++;
        it++;
    }
}

上面的实现遍历向量一次,复杂度O(N),N是向量的初始大小。每次迭代中进行的操作的复杂度为 O(logN)(由于the implementation of std::map)导致整体复杂度为 O(NlogN),远优于具有二次复杂度的初始算法。

请注意,这只是基于您的代码的粗略初始实现,对于您的初始代码和我建议的版本,还有其他可能的改进。一个例子是使用structclass 来包含每个术语而不是指针,并使您的代码更具可读性和更紧凑。另一个可能的改进可能是使用unordered_map 而不是map

【讨论】:

    【解决方案2】:

    我建议使用术语的结构使代码更具可读性:

    struct Term
    {
      int coefficient;
      char variable_name;
      int  exponent;
    };
    

    上述结构比 {6,2} 更容易模拟多项式项。
    您的代码变得更具可读性,这有助于减少缺陷的注入。

    然后多项式变为:

    typedef std::vector<Term> Polynomial;
    

    换句话说,多项式的容器(向量)。

    该结构还允许您按变量名称和降序系数(或指数)对容器进行排序。

    编辑 1:输入术语
    您可以为 Term 重载 operator&gt;&gt; 来输入一个术语:

    struct Term
    {
      // as above.
      friend std::istream& operator>>(std::istream& input, Term& t);
    };
    std::istream& operator>>(std::istream& input, Term& t)
    {
      input >> t.coefficient;
      input >> t.variable_name;
      input >> t.exponent;
      return input;
    }
    

    这允许您通过以下方式构建多项式:

    Polynomial p;
    Term t;
    while (input >> t)
    {
      p.push_back(t);
    }
    

    在我看来,这比您的设计和实现要简单得多且不易出错。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多