我在教自己的C ++。
我正在尝试组合多项式。为此,我定义了简单的类:
Polynomial<T>
,Term<T>
和Coefficient<T>
(也可能只是
complex<T>
)使用简单的值组合。我已经定义了所需的运算符重载。
通过对术语进行排序(std::sort
)来比较多项式。
我正在研究combineLikeTerms()
;调用此方法时将首先调用
另一个会对这个术语向量进行排序的成员方法。例如:
4x^3 + 5x^2 + 3x - 4
将是可能的结果排序向量。
问题:
我在这个向量上使用两个迭代器,我试图合并相邻的术语 相同的订单。
让我们说排序后的初始向量是这样的:
4x^3 - 2x^3 + x^3 - 2x^2 + x ...
在函数完成迭代后,临时堆栈向量将会出现 看起来像这个2x ^ 3 + x ^ 3 - 2x ^ 2 + x ...如果我们看起来仍然有类似的术语 这需要再次重构。
我该怎么做?我正在考虑使用递归。
// ------------------------------------------------------------------------- //
// setPolynomialByDegreeOfExponent()
// should be called before combineLikeTerms
template <class T>
void Polynomial<T>::setPolynomialByDegreeOfExponent()
{
unsigned int uiIndex = _uiNumTerms - 1;
if ( uiIndex < 1 )
{
return;
}
struct _CompareOperator_
{
bool operator() ( math::Term<T> a, Term<T> b )
{
return ( a.getDegreeOfTerm() > b.getDegreeOfTerm() );
} // operator()
};
stable_sort( _vTerms.begin(), _vTerms.end(), _CompareOperator_() );
} // setPolynomialByDegreeOfExponent
// ------------------------------------------------------------------------- //
// addLikeTerms()
template <class T>
bool Polynomial<T>::addLikeTerms( const Term<T>& termA, const Term<T>& termB, Term<T>& result ) const
{
if ( termA.termsAreAlike( termB ) )
{
result = termA + termB;
return true;
}
return false;
} // addLikeTerms
// ------------------------------------------------------------------------- //
// combineLikeTerms()
template <class T>
void Polynomial<T>::combineLikeTerms()
{
// First We Order Our Terms.
setPolynomialByDegreeOfExponent();
// Nothing To Do Then
if ( _vTerms.size() == 1 )
{
return;
}
Term<T> result; // Temp Variable
// No Need To Do The Work Below This If Statement This Is Simpler
if ( _vTerms.size() == 2 )
{
if ( addLikeTerms( _vTerms.at(0), _vTerms.at(1) )
{
_vTerms.clear();
_vTerms.push_back( result );
}
return;
}
// For 3 Ore More Terms
std::vector<Term<T>> vTempTerms; // Temp storage
std::vector<Term<T>>::iterator it = _vTerms.begin();
std::vector<Term<T>>::iterator it2 = _vTerms.begin()+1;
bool bFound = addLikeTerms( *it, *it2, result );
while ( it2 != _vTerms.end() )
{
if ( bFound )
{
// Odd Case Last Three Elems
if ( (it2 == (_vTerms.end()-2)) && (it2+1) == (_vTerms.end()-1)) )
{
vTempTerms.push_back( result );
vTempTerms.push_back( _vTerms.back() );
break;
}
// Even Case Last Two Elems
else if ( (it2 == (_vTerms.end()-1)) && (it == (_vTerms.end()-2)) )
{
vTempTerms.push_back( result );
break;
}
else
{
vTempTerms.push_back( result );
it += 2; // Increment by 2
it2 += 2; "
bFound = addLikeTerms( *it, *it2, result );
}
}
else {
// Push Only First One
vTempTerms.push_back( *it );
it++; // Increment By 1
it2++; "
// Test Our Second Iterator
if ( it2 == _vTerms.end() )
{
vTempTerms.push_back( *(--it2) ); // same as using _vTerms.back()
}
else
{
bFound = addLikeTerms( *it, *it2, result );
}
}
}
// Now That We Have Went Through Our Container, We Need To Update It
_vTerms.clear();
_vTerms = vTempTerms;
// At This point our stack variable should contain all elements from above,
// however this temp variable can still have like terms in it.
// ??? Were do I call the recursion and how do I define the base case
// to stop the execution of the recursion where the base case is a
// sorted std::vector of Term<T> objects that no two terms that are alike...
// I do know that the recursion has to happen after the above while loop
} // combineLikeTerms
有人可以帮我找到下一步吗?我很高兴听到所显示代码中的任何错误/效率问题。 我喜欢c ++
答案 0 :(得分:2)
这是我对现代C ++的看法。
注意使用有效系数零
来删除术语的额外优化自包含样本:http://liveworkspace.org/code/ee68769826a80d4c7dc314e9b792052b
更新:发布了 http://ideone.com/aHuB8
的 {{3}} 的c ++ 03版#include <algorithm>
#include <vector>
#include <functional>
#include <iostream>
template <typename T>
struct Term
{
T coeff;
int exponent;
};
template <typename T>
struct Poly
{
typedef Term<T> term_t;
std::vector<term_t> _terms;
Poly(std::vector<term_t> terms) : _terms(terms) { }
void combineLikeTerms()
{
if (_terms.empty())
return;
std::vector<term_t> result;
std::sort(_terms.begin(), _terms.end(),
[] (term_t const& a, term_t const& b) { return a.exponent > b.exponent; });
term_t accum = { T(), 0 };
for(auto curr=_terms.begin(); curr!=_terms.end(); ++curr)
{
if (curr->exponent == accum.exponent)
accum.coeff += curr->coeff;
else
{
if (accum.coeff != 0)
result.push_back(accum);
accum = *curr;
}
}
if (accum.coeff != 0)
result.push_back(accum);
std::swap(_terms, result); // only update if no exception
}
};
int main()
{
Poly<int> demo({ { 4, 1 }, { 6, 7 }, {-3, 1 }, { 5, 5 } });
demo.combineLikeTerms();
for (auto it = demo._terms.begin(); it!= demo._terms.end(); ++it)
std::cout << (it->coeff>0? " +" : " ") << it->coeff << "x^" << it->exponent;
std::cout << "\n";
}
答案 1 :(得分:1)
您需要将多项式视为对的序列(系数,变量):
[(coefficient1,变量1),(系数2,变量2),(coefficient3,variable3),...]
正如你所描述的那样,你从左到右迭代这个,每当变量部分相同时,将两个相邻的对组合成一个(当然这假设列表已经被< em>变量部分!)。
现在,如果此列表中有三个或更多元素共享其变量,会发生什么?好吧,然后继续合并它们。真的,不需要递归或任何复杂的事情。
在迭代期间的任何时候,您都会将当前对的变量部分与变量部分最后一次看到组合在一起。如果它们相同,则将它们组合起来然后继续。如果你得到的下一对仍然具有与上次见到的相同的变量部分,那么你再次组合它们。如果您正确执行此操作,则不应该留下任何重复项。
以下是如何执行此操作的示例。它的工作原理是创建一个新的对列表,然后遍历输入列表,对于输入列表的每个项目,它决定是将它与最后推送到新列表的项目组合,还是通过向新列表添加新元素:
#include <utility>
#include <vector>
#include <iostream>
typedef std::vector<std::pair<float,std::string>> Polynomial;
Polynomial combine_like_terms(const Polynomial &poly)
{
if (poly.empty())
return poly;
/* Here we store the new, cleaned-up polynomial: */
Polynomial clean_poly;
/* Now we iterate: */
auto it = begin(poly);
clean_poly.push_back(*it);
++it;
while (it != end(poly)) {
if (clean_poly.back().second == it->second)
clean_poly.back().first += it->first; // Like term found!
else
clean_poly.push_back(*it); // Sequence of like-terms ended!
++it;
}
return clean_poly;
}
int main()
{
Polynomial polynomial {
{ 1.0 , "x^2" },
{ 1.4 , "x^3" },
{ 2.6 , "x^3" },
{ 0.2 , "x^3" },
{ 2.3 , "x" },
{ 0.7 , "x" }
};
Polynomial clean_polynomial = combine_like_terms(polynomial);
for (auto term : clean_polynomial)
std::cout << '(' << term.first << ',' << term.second << ")\n";
std::cout.flush();
return 0;
}
如果需要,您可以轻松地再次进行此模板化 - 我使用float
表示系数,strings
表示变量部分。这只是一个代码示例,展示如何在不递归或并行使用大量迭代器的情况下轻松完成此任务。
哦,代码是为C ++ 11编写的。同样,它只是一个模型,可以针对C ++ 03进行调整。