欢迎阅读此内容的任何人。我对这个程序的问题是我似乎不理解如何将2个多项式顺序输入到链表中。我可以添加新的多项式或读取当前输入的多项式,但加法和减法给了我一些问题。这是我现在拥有的:
#include <iostream>
#include <cmath>
#include <cstddef>
using namespace std;
typedef float polyType;
struct polyInfo
{
int number;
int power;
polyInfo* link;
};
//typedef polyInfo* polyPtr;
//polyPtr head;
//polyPtr currPtr;
//polyPtr newNodePtr;
class Polynomial
{
private:
polyInfo *head;
int maxpow = 0;
public:
Polynomial(){}
void createPoly(int n, int p)
{
polyInfo *temp = new polyInfo();
temp->power = p;
temp->number = n;
temp->link = head;
head = temp;
if (maxpow < p)
{
maxpow = p;
}
}
void getPoly()
{
polyInfo *temp = head;
while (temp != NULL)
{
if (temp->number != 0)
{
cout << temp->number << "x^" << temp->power << " ";
}
temp = temp->link;
}
cout << "\n";
}
void addPoly()
{
polyInfo *temp = head;
while (temp != NULL)
{
if (temp->number != 0)
{
polyInfo *temp2 = head;
temp2 = temp2->link;
if (temp2->link != NULL)
{
if (temp->power == temp2->power)
{
temp->number = (temp->number)+(temp2->number);
temp2->number = 0;
temp = temp->link;
}
}
else
{
temp = NULL;
}
}
}
}
void subtractPoly()
{}
};
int main()
{
int menuNum;//used to see which menu option user chooses
int mainPower;
int mainNumber;
Polynomial mainPoly;
bool menu = true;
while (menu)
{
cout << "Enter 1 to create new polynomial"
<< "\nEnter 2 to read a polynomial"
<< "\nEnter 3 to add polynomials"
<< "\nEnter 4 to subtract polynomials"
<< "\nEnter 5 to end program :";
cin >> menuNum;
switch(menuNum)
{
case 1:
cout << "\nEnter the coefficient: ";
cin >> mainNumber;
cout << "\nEnter the exponent of X: ";
cin >> mainPower;
mainPoly.createPoly(mainNumber,mainPower);
break;
case 2:
mainPoly.getPoly();
break;
case 3:
mainPoly.addPoly();
break;
case 4:
mainPoly.subtractPoly();
break;
case 5:
cout << "End of program\n";
menu = false;
default:
cout << "\nInvalid Input, please try again\n\n";
break;
}
}
return 0;
}
我为代码中几乎没有任何评论而道歉。我通常会回过头来添加它们。我在main
中运行一个菜单,允许您输入一个新的多项式,读出它们,添加它们或减去它们。我有输入新的方法并将其读出给用户的方法。我已经在我的添加代码上得到了这么多,它不起作用。但问题不能通过两个单独的列表来解决,这是我在网上发现的大部分内容。它必须通过一个列表来完成,该列表包含每个节点中的数字和功率。
答案 0 :(得分:2)
首先:您正在处理用户输入,这些输入始终无效!如果用户输入e。 G。 x7
,operator>>
将失败并且cin
将保持错误状态(使后续流操作也失败),因此您将陷入无休止的循环中再次执行同一任务再次,取决于最后的成功输入。如果第一个用户输入无效,则根本不会初始化menuItem
,因此您甚至会遇到未定义的行为!所以:
if(std::cin >> menuItem)
{
// good case
}
else
{
// bad case!
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
最小处理:清除错误状态并忽略导致它的输入,在下一个循环中启动新的。您可以另外告知用户他/她做了什么......
首选适当的名称:getPoly
将多项式打印到控制台,然后将其重命名为printPoly
。同样,您的addPoly
函数看起来更像normalize
函数(如果有,但需要一些修复......)。
如果你真的想添加多项式,那么你需要两个!然后你需要决定:你想要将其他多项式添加到当前的多项式,还是要创建一个包含结果的新多项式?这将影响界面......您可能想要创建两者。请注意,对于这些操作,有默认的函数名称:operator+
和operator+=
。如果实现这些,您可以编写如下代码:
Polynomial x, y;
Polynomial z = x + y;
x += y;
现在,您似乎允许以任意顺序存储多项式元素。这将要求您在加法和减法时依赖O(n²)算法。这不是一个好主意......更好:保持多项式归一化为以下含义:
number
为0,则不要存储元素。如果一个元素在操作期间变为null,则将其删除。maxpow
成员(它相当于head->power
)。综上所述,我推荐另一个界面。之后的用法将是:
// create an initial polynomial:
Polynomial x(1, 3);
x += Polynomial(2, 2);
x += Polynomial(3, 1);
x.print();
// output: 3x^1 + 2x^2 + 3x^1
以下代码不完整,您需要自己贡献一些附加内容(例如,PolyInfo结构的适当构造函数;顺便说一下:将此内容作为内部类!)... < / p>
Polynomial(int n = 0, int p = 0)
: head(nullptr)
{
if(n)
{
head = new PolyInfo(n, p);
}
}
static Polynomial operator+(Polynomial const& x, Polynomial const& y)
{
PolyInfo* result;
PolyInfo* tmp = nullptr;
PolyInfo* ix = x.head;
PolyInfo* iy = y.head;
while(ix || iy)
{
if(ix && (!iy || ix->power > iy->power))
{
result = new PolyInfo(*ix);
ix = ix->link;
}
else if(iy && (!ix || iy->power > ix -> power))
{
result = new PolyInfo(*iy);
iy = iy->link;
}
else
{
int n = ix->number + iy->number;
ix = ix->link;
iy = iy->link;
if(n == 0)
// ignore this node!!!
continue;
result = new PolyInfo(n, ix->power);
}
result->link = tmp;
tmp = result;
}
// yet in r e v e r s e order!
result = nullptr;
while(tmp)
{
PolyInfo* next = tmp->link;
tmp->link = result;
result = tmp;
tmp = next;
}
}
Polynomial& operator+=(Polynomial const& other)
{
*this = *this + other;
return *this;
}
第一步完成......
非常确定您不想为operator-
重复此代码,因此我们可能有一个共同的功能,因此,将当前的operator+
设为私有并重命名,并添加其他参数:< / p>
static Polynomial calculate
(
Polynomial const& x, Polynomial const& y,
int(*op)(int, int)
)
{ /* ... */ }
现在还有一条线要改变(在两个节点功率相等的情况下):
int n = op(ix->number, iy->number);
现在添加两个新运算符:
static Polynomial operator+(Polynomial const& x, Polynomial const& y)
{
return calculate(x, y, [](int x, int y) { return x + y; });
}
static Polynomial operator-(Polynomial const& x, Polynomial const& y)
{
return calculate(x, y, [](int x, int y) { return x - y; });
}
现在,为了这个工作,我们还需要一个复制构造函数和复制赋值,以防止内存泄漏;析构函数(参见rule of three)(但见下文!!!):
Polynomial(Polynomial const& other)
{
// make a deep copy by copying all elements
// easiest is creating the copy in inverse order and
// then reverting it similar as in calculate
// have a common function for then!
}
Polynomial& operator=(Polynomial const& other)
{
this->~Polynomial();
new(this)Polynomial(other);
return *this;
}
好的,上面的赋值运算符异常且效率低(但至少不正确,并且很容易实现......),它会删除当前对象并通过复制构造函数重新创建它。这将导致删除所有节点并根据需要重新创建它们。更好:重用已经存在的节点,将值从另一个多项式复制到。然后在另一个中创建更多的副本,或者删除当前存在的更多副本。将此作为练习。但是,您可以在复制构造函数中使用它:
Polynomial(Polynomial const& other)
: Polynomial()
{
*this = other;
}
析构函数只会删除所有存在的节点。
完整性:Rule of five ...
这不是必须的,但提供了很好的优化机会:
Polynomial(Polynomial&& other)
: Polynomial()
{
std::swap(this->head, other->head);
// swaps nullptr into other...
}
Polynomial& operator=(Polynomial&& other)
{
std::swap(this->head, other->head);
// huh, memory leak?
// no, other will delete contents previously owned by this
// as soon as running out of scope...
return *this;
}
这看起来像是一个练习任务,因此您可能不被允许,但如果您是,请使用STL容器而不是您自己的链接列表:e。 G。 std::list
用于双向链接列表(使迭代更容易,特别是避免以逆序创建并在之后还原),std::forward_list
用于单个链接列表,甚至std::vector
。这将使您从上面的所有内存管理中解脱出来,并且默认的复制/移动构造函数/赋值和析构函数适合您(因为相应的容器等价物将被隐式调用)...
最后:以上所有代码都是未经测试的,可能存在错误,但它应该为您指明方向。