通过c ++

时间:2017-01-30 16:44:24

标签: c++ vector iterator traversal

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

假设我们可以用两个成员的int数组表示每个术语,第一个成员显示变量,第二个成员是系数。例如, 4a 3b 可分别由(1,4)和(2,3)表示。在这些例子中,我们用基于字母顺序的整数(a:1,b:2,c:3,...)显示了变量(a,b,..)。

因此,多项式可以表示为向量< -int *>这些条款。例如,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++;  
    }
}

我感谢所有能告诉我代码问题的人,以及如何提高代码速度。

2 个答案:

答案 0 :(得分:1)

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

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

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

多项式变为:

typedef std::vector<Term> Polynomial;

简而言之,这表明多项式 Terms 的容器(向量)。

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

编辑1:条款输入
您可以重载术语的operator>>以输入术语:

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);
}

在我看来,比您的设计和实现更简单,更不容易出错。

答案 1 :(得分:1)

您的代码中肯定会有一些变化。但是,由于您主要关心的是效率,我建议您采取不同的算法采取的第一个行动。

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

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

正如您可能已经注意到的那样,此算法的复杂性为 O(N 2 ,这是您的代码效率低下的主要原因。

作为替代方案,您可以迭代向量并将值放到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