零。 理论知识
视频:多项式运算
a. 如何表示
我们用线性表去表示一元多项式。
struct Node{
int r; // 系数
int e; // 指数
};
struct List{
Node data[10000+5];
int len;
};
1.第一个结构体Node中的每一项(节点)都表示一元多项式中的一项,包含了系数r 和 指数e
2.第二个结构体有两部分。一个是len表示当前的长度,即当前的一元多项式用到了多少项;另一个是一个结构体数组(即Node),结构体数组中的每一项就表示了一元多项式中的一项
注意: 这里不再是链表了,而只是一个结构体数组
b. 如何实现功能
与链表的各个操作类似,线性表去进行一元多项式的运算题目一般也包含两部分
1. 一个是各个题目都通用的基础函数,如inputlist Printlist.....——见“壹”部分
2. 另一个则是每道题具体实现要用到的函数,如实现相加功能的函数,实现求导功能的函数......——见“贰”部分
壹。 一元多项式的基本操作函数
a. 输入函数
// 输入多项式
List InputList()
{
//先设出变量list,并初始化其中的长度len为0
List list;
list.len = 0;
int r,e;
while(cin>>r>>e)
{
if( r==-1 && e==-1 )//输入到-1 -1 则break跳出循环
{
break;
}
else
{
list.data[list.len].r = r;
list.data[list.len].e = e;
list.len++;
}
}
return list;
}
此时可以巧妙地利用list.len去知道当前输入到第几项了,从而避免了再设一个变量i
b. 输出函数
// 输出多项式
void PrintList(const List& list)
{
int l = list.len;
//特判一下结果为0的情况 和 答案多项式为空的情况
if( l==0 || l==1 && list.data[0].r==0 )
{
cout<<"0";
}
for( int i = 0 ; i<l ; i++ )
{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
}
cout<<endl;
}
就是一个比较简单的数组遍历,但是要注意一些题目中提出的输出要求去进行输出特判(如答案多项式为0......)
贰。 几道题目和其中具体的函数实现
a. 一元多项式的求和(附加代码模式)
题目:
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[10000+5];
int len;
};
// 输出多项式
void PrintList(const List& list)
{
int l = list.len;
//特判一下结果为0的情况 和 答案链表为空的情况
if( l==0 || l==1 && list.data[0].r==0 )
{
cout<<"0";
}
for( int i = 0 ; i<l ; i++ )
{
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
}
cout<<endl;
}
// 输入多项式
List InputList()
{
//先设出变量list,并初始化其中的长度len为0
List list;
list.len = 0;
int r,e;
while(cin>>r>>e)
{
if( r==-1 && e==-1 )//输入到-1 -1 则break跳出循环
{
break;
}
else
{
list.data[list.len].r = r;
list.data[list.len].e = e;
list.len++;
}
}
return list;
}
// 多项式求和
List add(const List& list1, const List& list2)
{
//去设出答案多项式
List list3;
list3.len=0;
//用i和j两个指针分别指向list1和list2 从而进行遍历
int i = 0 , j = 0;
int l1 = list1.len , l2 = list2.len;
//去对a和b中的每个节点逐一比较,此时是降幂排列 所以直接一一比较即可
//while不断循环直到两个数组有一个先被遍历完了
while( i<l1 && j<l2 )
{
if( list1.data[i].e == list2.data[j].e )
{
if(list1.data[i].r + list2.data[j].r == 0 )
{
i++,j++;
}
else
{
list3.data[list3.len].e = list1.data[i].e;
list3.data[list3.len].r = list1.data[i].r + list2.data[j].r;
i++,j++,list3.len++;
}
}
else if( list1.data[i].e > list2.data[j].e )
{
list3.data[list3.len].e = list1.data[i].e;
list3.data[list3.len].r = list1.data[i].r;
i++,list3.len++;
}
else if( list1.data[i].e < list2.data[j].e )
{
list3.data[list3.len].e = list2.data[j].e;
list3.data[list3.len].r = list2.data[j].r;
j++,list3.len++;
}
}
//退出了while循环只能说明其中至少有一个数组循环完了,
//但另外一个可能还有东西;此时全部加到答案数组后面即可
//(为了方便 直接写两个while循环避免判断了)
while( i<l1 )
{
list3.data[list3.len].e = list1.data[i].e;
list3.data[list3.len].r = list1.data[i].r;
i++,list3.len++;
}
while( j<l2 )
{
list3.data[list3.len].e = list2.data[j].e;
list3.data[list3.len].r = list2.data[j].r;
j++,list3.len++;
}
return list3;
}
int main()
{
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list1 = InputList();
List list2 = InputList();
List list = add(list1, list2);
PrintList(list);
return 0;
}
见实现求和函数的注释:
1.由于本来就是降幂排序,所以直接用两个指针分别指向list1和list2;并不断地进行比较直到有一个list被循环完
2.此时再去把另一个list全部加到答案list里即可(如果有的话)
b. 一元多项式的乘法运算
题目:
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> //因为后面要用到sort函数
using namespace std;
struct Node{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[10000+5];
int len;
};
//自定义的比较函数
bool cmp( Node a , Node b ) //要明白此时我们要排序比较的是两个Node 所以传入参数的数据类型是Node
{
return a.e>b.e; //此时是降序排序 所以是大于号
}
// 输出多项式
void PrintList(const List& list)
{
int l = list.len;
//特判一下结果为0的情况
if( l==0 || l==1 && list.data[0].r==0 )
{
cout<<"0 0";
}
for( int i = 0 ; i<l ; i++ )
{
if(list.data[i].r!=0)
cout<<list.data[i].r<<" "<<list.data[i].e<<" ";
}
cout<<endl;
}
// 输入多项式
List InputList()
{
List list;
list.len = 0;
int r,e;
int n;
cin>>n;
while(n--)
{
cin>>r>>e;
list.data[list.len].r = r;
list.data[list.len].e = e;
list.len++;
}
return list;
}
// 多项式求和
List mul(const List& list1, const List& list2)
{
//去设出答案链表
List list3;
list3.len=0;
//用i和j两个指针分别指向list1和list2 从而进行遍历
//1.先去无脑地把所有项都乘一遍
int i = 0 , j = 0;
int l1 = list1.len , l2 = list2.len;
for( int i = 0 ; i<l1 ; i++ )
{
for( int j = 0 ; j<l2 ; j++ )
{
if(list1.data[i].r)
list3.data[list3.len].e = list1.data[i].e + list2.data[j].e;
list3.data[list3.len].r = list1.data[i].r * list2.data[j].r;
if( list3.data[list3.len].r != 0 ) list3.len++; //如果相乘后系数为0 则不计入list3中,自然也不会加他的长度
}
}
//2.进行排序(降幂排序)
int l3 = list3.len;
sort(list3.data,list3.data+l3,cmp);//利用sort让list3.data也为降序排列
//3.合并同类项
if(l3>2) //特判一下 如果list3中只有一个元素则不用去合并了
{
for(int p=1;i<l3;i++)
{
if(list3.data[i].e==list3.data[i-1].e) //若指数一样就把系数合并
{
list3.data[i].r+=list3.data[i-1].r;
list3.data[i-1].r=0;
}
}
}
return list3;
}
int main()
{
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list1 = InputList();
List list2 = InputList();
List list = mul(list1, list2);
PrintList(list);
return 0;
}
见相乘部分的算法
首先,我们思考一下自己手写计算多项式的步骤。应该是先把两个多项式的每项都相乘(指数和 系数乘),再排序 , 最后合并同类项(指数相同)即可
1. 先用两个指针分别指向list1和list2,去用一个双重for循环无脑地把所有项都相乘一遍
注意: 此时如果相乘的结果包含了系数为0的项,则不应该计入答案数组中
2. 对list3进行降幂排序(利用sort函数去进行排序)
要注意我们是要对结构体list3中的结构体数组data【】进行排序,所以传入sort函数的应该是list3.data
3. 降幂排序后,再去合并同类项
c. 一元多项式的求导(附加代码模式)
题目:
代码实现:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct Node
{
int r; // 系数
int e; // 指数
};
// 线性表存储一元多项式
struct List{
Node data[10000+5];
int len;
};
// 输出多项式
void PrintList(const List& list)
{
//特判一下特殊情况
if( list.len==1 && list.data[0].e==0 )
{
cout<<"0";
}
else
{
//去进行遍历输出
for (int i = 0; i < list.len; i++)
{
cout << list.data[i].r << " " << list.data[i].e << " ";
}
}
cout << endl;
}
// 输入多项式
List InputList()
{
//先设出链表(头节点),并进行初始化(使其长度为0)
List list;
list.len = 0;
while (1)
{
int r, e;
cin >> r >> e;
if (r == -1 && e == -1) break; //如果-1 -1 则停止输入,跳出循环
//正常情况下则把系数与指数输入
//注:要与前面的区分好这里的list就只是一个普通的结构体而非结构体指针了 所以不再需要->了
list.data[list.len].r = r;
list.data[list.len].e = e;
list.len++;
}
return list;
}
// 多项式求导
List getDerivation(const List& list)
{
List newlist;
newlist.len = 0;
//特判一下特殊情况
if( list.len==1 && list.data[0].e==0 || list.len==0 )
{
newlist.data[0].r = list.data[0].r;
newlist.data[0].e = list.data[0].e;
newlist.len++;
}
//遍历进行求导
//在这里 直接把系数为0的项干掉了
for (int i = 0; i < list.len; i++)
{
if (list.data[i].e != 0)
{
newlist.data[newlist.len].r = list.data[i].r * list.data[i].e;
newlist.data[newlist.len].e = list.data[i].e - 1;
newlist.len++;
}
}
return newlist;
}
int main(){
// freopen("/config/workspace/answer/DataStructure/test.in","r",stdin);
List list = InputList();
List newlist = getDerivation(list);
PrintList(newlist);
return 0;
}
进行常规求导操作即可