Представление полинома со связанными списками
Заранее спасибо. Для моего класса C++ мне поручено представлять полином, такой как (MyPoly= 7x^6*y^4 + 4x^4*y^5 - 8x^5*y^3 – 9x + 8)
использование связанных списков и создание классов Node & Poly, чтобы помочь выразить это.
Я не знаю, как представить многочлен с X и Y в связанном списке.
У меня есть идея построить связанный список для представления полинома, как 7 6 4 -> 4 4 5 -> -8 5 3 ->-9 1 0 -> 8 0 0 ->NULL
Я новичок в этом, поэтому любой пример кода или псевдокод будет иметь большую помощь.
Я придумал этот код здесь (отправная точка), но я думаю, что он будет работать только для одной переменной, а не для двух (7x^6*... но не 7x^6*y^4). Еще раз спасибо:).
4 ответа
Вы думали, или вам разрешено работать с представлением полиномов Хорнера? Это не только гораздо более эффективный способ вычисления полиномиальных значений, но во многих случаях это может привести к более разреженной структуре данных. Например, полином:
эквивалентно следующему выражению:
Итак, есть 3 вещи, на которые стоит обратить внимание:
- На самом деле, одна замечательная особенность этой схемы (хотя и не имеющая прямого отношения к вашему вопросу) состоит в том, что ее вычисление выполняется намного быстрее, поскольку вы экономите много умножений.
- Индекс полинома напрямую зависит от длины выражения
- Все элементы в выражении изоморфны, независимо от степени. Это также верно для каждой арности.
Так что в этом счастливом случае выбранный мною полином может быть очень легко и эффективно сохранен как следующий список / массив:
[7, 5, 1, -4, 1, 8, 1, -7]
или, если хотите, в виде связного списка чисел [x_mult|sum]: [7|5]->[1|4]->[1|8]->[1|-7]
тогда как вы знаете, что элементы с четными индексами умножаются на x и добавляются к следующему элементу, схема довольно проста.
#include <iostream>
using namespace std;
int main()
{
// the x you want to calculate
int x = 1;
// the horner-representation of your polynom
int A[8] {7, 5, 1, -4, 1, 8, 1, -7};
int partial;
int result = 1;
// run calculations following horner-schema
for (int i = 0; i < 8; i++) {
if (i%2==0){
partial = A[i]*x; // this mult. is only needed at i=0
result *= partial;
} else{
partial = A[i];
result += partial;
}
}
cout << "x=" << x << ", p(x)=" << result << endl;
return 0;
}
Проблемы: Вы можете значительно улучшить его производительность и использование памяти, если подавите нечетные индексы и примете "1" как должное, сохранив первые 7 в другом месте. Кроме того, поскольку индекс напрямую зависит от длины списка, полиномы, такие как будет иметь очень неэффективное представление.
Обходной путь для проблем с памятью. Возможный обходной путь - наследовать ваш ListElement как ExpandedListElement, так что числа в его контейнерах интерпретируются не как факторы, а как число повторений. Таким образом, ExpandedListElement [1000|a] будет означать, что в вашем списке есть тысяча ListElements, которые выглядят так: [1|a]. Таким образом, в данном примере x^1000+3 будет два элемента: ExpandedListElement[999|0]->ListElement[1|3]. Вам также понадобится метод для выполнения цикла, который я опускаю (если вам нужен этот обходной путь, дайте мне знать, и я опубликую его).
Я не тестировал это подробно, но я предполагаю, что это хороший подход также для двух или более переменных. Я оставил также остальные детали ОО-реализации отдельно, но основные DS и операции есть и их должно быть легко внедрить в классы. Если вы попробуете, дайте мне знать, как это работает!
ура
Andres
Быстрое решение не очень чистое:
MyPoly = 7x ^ 6 * y ^ 4 + 4x ^ 4 * y ^ 5 - 8x ^ 5 * y ^ 3 - 9x + 8
#include <list>
class factor;
class polynomial{
public:
std::list<factor> factors;
};
class factor{
public:
factor()=default;
factor(int constant,int x_pow,int y_pow):constant(constant),x_pow(x_pow),y_pow(y_pow){}
int constant;
int x_pow;
int y_pow;
};
int main()
{
polynomial MyPoly;
MyPoly.factors.emplace_back(7,6,4);
MyPoly.factors.emplace_back(4,4,5);
MyPoly.factors.emplace_back(8,5,3);
MyPoly.factors.emplace_back(9,1,0);
MyPoly.factors.emplace_back(8,0,0);
}
Я думаю, что вы можете представлять полином с матрицей, а не связным списком или чем-то еще.
|X^0|x^1|x^2|x^3
---|---|---|---|---
y^0| | | |
---|---|---|---|---
y^1| | | |
---|---|---|---|---
y^2| | | |
---|---|---|---|---
y^3| | | |
В каждой ячейке вы должны хранить коэффициенты x^x'и y^y'. И вы можете определить операции проще.
Вы можете использовать Boost.uBLAS для матричных операций.
Это был бы один из способов сделать это:
Особенности дизайна:
1. Рассмотрим полином как список узлов
2. Каждый узел может состоять из подузлов.
Итак, ваши определения классов будут:
class Polynomial
{
list<nodes> termList;
};
class Node
{
list<SubNodes> subnodelist;
};
template<class T>
class subNode
{
int coefficient;
int power;
T variable;
};
Примечание: не проверен код на правильность.