本节讨论如何用带头结点的线性链表的基本操作来实现一元多项式的加减乘运算。
由于笔者使用的是严蔚敏的《数据结构》,故本解决方案主要来自教材37页和42页的整合。而代码的风格仿照B站的数据结构老师王卓。
程序分为一个主文件main.cpp和头文件operator.h。具体如下:
mian.cpp
#include <iostream>
#include "operator.h"
using namespace std;
int main(){
LinkList Pa,Pb;
int choice = 1;
while(1){
display();
cout<<"请输入操作:";
cin>>choice;
switch(choice){
case 1:
input(Pa,Pb);
AddList(Pa,Pb);
cout<<"以上两个式子相加的多项式为:";
PrintList(Pa);
break;
case 2:
input(Pa,Pb);
SubtractList(Pa,Pb);
cout<<"以上两个式子相减的多项式为:";
PrintList(Pa);
break;
case 3:
input(Pa,Pb);
MultiplyList(Pa,Pb);
cout<<"以上两个式子相乘的多项式为:";
PrintList(Pa);
break;
case 0:
return 0;
}//switch
}//while
}//main
operator.h
#include <iostream>
using namespace std;
//预定义类型和变量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
//一个带头结点的链表
typedef struct{ //数据类型
float coef; //系数
int expn; //指数
}ElemType,term;
typedef struct LNode{ //结点类型
ElemType data;
struct LNode *next;
}LNode, *LinkList;
Status MakeNode(LinkList &p,ElemType e){
//分配由p指向的值为e的结点,并返回OK;若分配失败,则返回ERROR
p = new LNode;
if(!p)
return ERROR;
p->data = e;
p->next = NULL;
return OK;
}//MakeNode
Status FreeNode(LinkList &p){
//释放p所值的结点
delete p;
p = NULL;
return OK;
}//FreeNode
Status DeleteNode(LinkList &pa,LinkList &pb){
//删除pa后面的结点pb
pa->next = pb->next;
return OK;
}//DeleteNode
LinkList PriorNode(LinkList L,LinkList p){
//搜索链表L中结点p的前一个结点
LinkList q;
q = L->next;
if(q == p){
return NULL;
}//if
else{
while(q->next != p){
q = q->next;
}
return q;
}//else
}//PriorNode
Status InitList(LinkList &L){
//构造一个空的线性链表
L = new LNode;
L->next = NULL;
return OK;
}//InitList
Status CreateList(LinkList &L){
//创建新的链表
InitList(L);
cout<<"请分别输入链表的系数和指数,当指数为-1时停止输入:"<<endl;
LNode *s,*r;
r = L;
ElemType e;
cin>>e.coef>>e.expn;
while(e.expn != -1){
s = new LNode;
s->data = e;
r->next = s;
r = s;
cin>>e.coef>>e.expn;
}
r->next = NULL;
return OK;
}//CreateList
Status DestroyList(LinkList &L){
//销毁线性链表L,L不再存在
LNode *p;
while(L){
p = L;
L = L->next;
delete p;
}
return OK;
}//DestroyList
Status ClearList(LinkList &L){
//将线性链表L重置为空表,并释放原链表的结点空间
LNode *p,*s;
p = L->next;
while(p){
s = p->next;
delete p;
p = s;
}
L->next = NULL;
return OK;
}//ClearList
void PrintList(LinkList L){
LinkList p;
p = L->next;
while(p){
cout<<p->data.coef<<"*x^"<<p->data.expn;
p = p->next;
if(p && p->data.coef>0) cout<<"+";
}//while
cout<<endl;
}//PrintList
int compare(term a,term b){
//比较链表指数的大小,小于,等于,大于返回-1 0 1
if(a.expn<b.expn) return -1;
if(a.expn>b.expn) return 1;
return 0;
}//compare
void OppositeList(LinkList &L){
LinkList p;
p = L->next;
while(p){
p->data.coef *= -1;
p = p->next;
}
}//OppositeList
Status LocateElemP(LinkList L,ElemType e,LinkList &q,int (*compare)(term,term)){
//若有序链表L中存在与e满足有序判定函数compare()取值为0的元素,则q指示L中第一个值为e的结点位置,并返回TRUE
//否则,q指示第一个与e满足有序判定函数compare()取值为1的元素的前驱,并返回FALSE
LinkList prior,p;
p = L; //p指向当前结点
do{
prior = p;
p = p->next;
}while(p && (*compare)(p->data,e)<0);
if(!p || compare(p->data,e)>0){
q = prior;
return FALSE;
}//if
else{
q = p;
return TRUE;
}//else
}//LocateElemP
void OrderInsert(LinkList &L,ElemType e,int (*compare)(ElemType,ElemType)){
//按有序判定函数compare()的约定,将值为e的结点插入到有序链表L的适当位置上
LinkList p,q;
if(LocateElemP(L,e,q,compare)){ //链表中存在该指数项
q->data.coef += e.coef;
if(!q->data.coef){ //系数为0
p = PriorNode(L,q);
if(!p) p = L;
DeleteNode(p,q);
FreeNode(q);
}//if
}//if
else{ //链表中不存在该指数项
MakeNode(p,e); //创建结点 插入
p->next = q->next;
q->next = p;
}//else
}//OrderInnsert
void AddList(LinkList &La,LinkList &Lb){
//链表La = La+Lb
LinkList ha,hb; //头结点
LinkList pa,pb; //当前结点
ha = La; pa = ha->next;
hb = Lb; pb = hb->next;
float sum;
while(pa && pb){
switch(compare(pa->data,pb->data)){
case -1: //链表La当前结点的指数小于链表Lb
ha = pa;
pa = pa->next;
break;
case 0: //两个链表当前结点指数相等
sum = pa->data.coef+pb->data.coef;
if(sum != 0.0){ //相加不等于0
pa->data.coef = sum;
ha = pa;
}
else{ //相加等于0
DeleteNode(ha,pa); //删除结点pa
FreeNode(pa);
}
//删除结点pb
DeleteNode(hb,pb);
FreeNode(pb);
pb = hb->next;
pa = ha->next;
break;
case 1: //链表La当前结点的指数大于链表Lb
DeleteNode(hb,pb); //Lb
pb->next = ha->next; //La
ha->next = pb;
pb = hb->next;
ha = ha->next;
break;
}//switch
}//while
if(pb) ha->next = pb; //将Lb剩下的子链接到Lb
FreeNode(hb);
}//AddList
void SubtractList(LinkList &La,LinkList &Lb){
//La = La-Lb
OppositeList(Lb); //链表Lb变为相反数
AddList(La,Lb);
}//SubtractList
void MultiplyList(LinkList &La,LinkList &Lb){
//多项式相乘La = La*Lb
LinkList Lc; //临时多项式链表Lc
InitList(Lc); //初始化Lc
LinkList pa,pb;
term a,b,c;
pa = La;
if(La->next!=NULL && Lb->next!=NULL){
pa = pa->next;
while(pa){
a = pa->data;
pb = Lb->next;
while(pb){
b = pb->data;
c.coef = a.coef*b.coef;
c.expn = a.expn+b.expn;
OrderInsert(Lc,c,compare);
pb = pb->next;
}//while
pa = pa->next;
}//while
DestroyList(Lb);
ClearList(La);
La = Lc;
}//if
else{
//do nothing链表为空
}//else
}//MultiplyList
//显示界面
void display(){
cout<<"---一元多项式四则运算---"<<endl;
cout<<"---输入数字1选择相加----"<<endl;
cout<<"---输入数字2选择相减----"<<endl;
cout<<"---输入数字3选择相乘----"<<endl;
cout<<"---输入数字0选择退出----"<<endl;
}//display
//输入界面
void input(LinkList &La,LinkList &Lb){
cout<<"请输入第一个多项式:"<<endl;
CreateList(La);
PrintList(La);
cout<<"请输入第二个多项式:"<<endl;
CreateList(Lb);
PrintList(Lb);
}//input