实验名称 一元多项式的相加、相减、相乘
一元多项式相加:
#include <stdio.h>
#include <stdlib.h>
typedef struct tagNode
{
float coef;
int exp;
struct tagNode *pNext;
};
typedef struct tagNode Node;
typedef struct tagNode *pNode;
// 将结点插入到链表的适当位置,这是一个指数升序排列的链表
void insertList(pNode head, pNode pnode) // 链表头结,待插入的结点
{
pNode pPre = head;
while(pPre->pNext != NULL)
{
if (pPre->pNext->exp > pnode->exp)
{
pnode->pNext = pPre->pNext;
pPre->pNext = pnode;
break;
}
else if(pPre->pNext->exp == pnode->exp) // 添加一个判断,判断新加入的结点和之前已加入结点是否有指数相同情况
{ // 即合并同类项
pPre->pNext->coef = pPre->pNext->coef+pnode->coef;
free(pnode);
break;
}
pPre = pPre->pNext;
}
if (pPre->pNext == NULL) // 待插入的结点指数最大,直接插入到结点最后
{
pPre->pNext = pnode;
}
}
// 输出链表
void printLinkedList(pNode head)
{
pNode temp = head->pNext;
while (temp != NULL)
{
printf(" %g", temp->coef);
printf("x^%d +", temp->exp);
temp = temp->pNext;
}
printf("\b \n");
}
// 两链表相加
void add_poly(Node *pa, Node *pb)
{
Node *p = pa->pNext; // 链表1,多项式结果放在链表1
Node *q = pb->pNext; // 链表2
Node *pre = pa;
Node *temp; // 临时用
float x;
while(p != NULL && q != NULL) // 当两个链表都不为空
{
if (p->exp < q->exp) // 链表1的指数小于链表2的指数
{
pre = p;
p = p->pNext; // 链表1存放加和数据,不用操作。只需后移指针
}
else if(p->exp == q->exp) // 链表1指数和链表2指数相等
{
x = p->coef + q->coef; // x存放系数和。判断x是否为0
if (x != 0) // x不为0则在链表1中更新加和的值
{
p->coef = x;
pre = p;
}
else // x为0则从链表1中移除该项
{
pre->pNext = p->pNext;
free(p);
}
p = pre->pNext; // p指向下一个判断的结点
// 链表2结点的删除部分。
temp = q;
q = q->pNext;
free(temp);
}
else // 如果链表1指数大于链表2指数,把当前结点插入链表1比较结点前
{
temp = q->pNext;
q->pNext = p;
pre->pNext = q;
pre = q;
q = temp;
}
}
if (q) // 如果链表2比链表1长,则需要把2多余部分加到1后面。反之不用操作
{
pre->pNext = q;
}
free(pb);
}
int main()
{
pNode head1 = (pNode)malloc(sizeof(struct tagNode)); // 给头指针分配空间
pNode head2 = (pNode)malloc(sizeof(struct tagNode));
int exp, temp1; // 指数
float coef, coef2; // 系数
pNode pTemp = NULL;
head1->pNext = NULL;
head2->pNext = NULL;
// 读入多项式1
printf("请输入要放入链表1中的数据,顺序为\'系数,指数\'。若多项式结束,则以0结尾。\n");
// 读入数据,以0,0结尾,把数据插入链表中。
scanf("%f,%d", &coef, &exp);
while(coef != 0 || exp != 0)
{
pTemp = (pNode)malloc(sizeof(struct tagNode));
pTemp->coef = coef;
pTemp->exp = exp;
pTemp->pNext = NULL;
insertList(head1, pTemp);
//temp1 = exp;
//temp2 = coef;
scanf("%f,%d", &coef, &exp)
}
printf("指数升序排列的多项式1为:\n");
printLinkedList(head1);
printf("\n");
// 读入多项式2
printf("请输入要放入链表2中的数据,顺序为\'系数,指数\'。若多项式结束,则以0结尾。\n");
// 读入数据,以0,0结尾,把数据插入链表中。
scanf("%f,%d", &coef, &exp);
while(coef != 0 || exp != 0)
{
pTemp = (pNode)malloc(sizeof(struct tagNode));
pTemp->coef = coef;
pTemp->exp = exp;
pTemp->pNext = NULL;
insertList(head2, pTemp);
scanf("%f,%d", &coef, &exp);
}
printf("指数升序排列的多项式2为:\n");
printLinkedList(head2);
printf("\n");
// 多项式相加
add_poly(head1, head2);
printf("多项式相加的结果为:\n");
printLinkedList(head1);
printf("\n");
return 0;
}
一元多项式相减:
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define TRUE 1
#define FALSE 0
typedef int Status;//为了方便算法可用性,算法的Status可以通过这里可改
#include <stdio.h>
#include <stdlib.h>
typedef struct{//项的表示,多项式的项作为LinkList的数据元素
int coef;//系数
int expn;//指数
}term, ElemType;//两个类型:term用于本ADT,ElemType为LinkList的数据对象名
typedef struct LNode{//节点类型
ElemType data;//这里表示了每一项,其指数和系数
struct LNode *next;
}*Link, *Position;
typedef struct{//链表类型
Link head, tail;//分别指向线性链表中的头结点和最后一个结点
int len;//指示线性链表中数据元素的个数
}LinkList;//每一项组成一个列表
typedef LinkList polynomial;
Status InitList(LinkList *L)
{ /* 构造一个空的线性链表 */
Link p;
p = (Link)malloc(sizeof(LNode)); /* 生成头结点 */
if (p)
{
p->next = NULL;
(*L).head = (*L).tail = p;
(*L).len = 0;
return OK;
}
else
return ERROR;//内存分配不够
}
Status MakeNode(Link *p, ElemType e)
{ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */
*p = (Link)malloc(sizeof(LNode));
if (!*p)
return ERROR;
(*p)->data = e;
return OK;
}
Status InsFirst(LinkList *L, Link h, Link s) /* 形参增加L,因为需修改L */
{ /* h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前 */
s->next = h->next;
h->next = s;
if (h == (*L).tail) /* h指向尾结点 */
(*L).tail = h->next; /* 修改尾指针 */
(*L).len++;
return OK;
}
Position GetHead(LinkList L)
{ /* 返回线性链表L中头结点的位置 */
return L.head;
}
Status SetCurElem(Link p, ElemType e)
{ /* 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值 */
p->data = e;
return OK;
}
Status LocateElemP(LinkList L, ElemType e, Position *q, int(*compare)(ElemType, ElemType))
{ /* 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中 */
/* 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数 */
/* compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式) */
Link p = L.head, pp;
do
{
pp = p;
p = p->next;
} while (p && (compare(p->data, e)<0)); /* 没到表尾且p->data.expn<e.expn */
if (!p || compare(p->data, e)>0) /* 到表尾或compare(p->data,e)>0 */
{
*q = pp;
return FALSE;
}
else /* 找到 */
{/* 没到表尾且p->data.expn=e.expn */
*q = p;
return TRUE;
}
}
Status Remove_Polyn(LinkList *L, Link q)
{ //由于项的指数为0,删除掉已有的项
Link p, h;
h = L->head;
while (h->next != q)
{
h = h->next;
}
//找到了
if (q == L->tail)
{//删除的如果是表尾,改变表尾
L->tail = h;
}
h->next = q->next;
free(q);
L->len--;
return OK;
}
int cmp(term a, term b) // CreatPolyn()的实参
{ // 依a的指数值<、=或>b的指数值,分别返回-1、0或+1
if (a.expn == b.expn)
return 0;
else
return (a.expn - b.expn) / abs(a.expn - b.expn);
}
void CreatPolyn(polynomial &p, int m)
{//输入m项的系数和指数,建立表示一元多项式的有序链表P
InitList(&p);//初始化多项式链表
Link h = GetHead(p);//设置头结点的数据元素
ElemType e;//头结点设置
Position q, s;
e.coef = 0; e.expn = -1; SetCurElem(h, e);//设置头结点的元素
for (int i = 1; i <= m; ++i)//依次输入m个非零项
{
printf( "第 %d 项的系数:",i);
scanf("%d",&e.coef);
printf("第 %d 项的指数:",i);
scanf("%d",&e.expn);
if (!LocateElemP(p, e, &q, cmp))//当前链表中不存在该指数项
{
if (e.coef != 0)//不等于才插入
if (MakeNode(&s, e))InsFirst(&p, q, s);//生成结点并插入链表
}
else//当前链表中存在该指数项,增加其系数
{
q->data.coef = q->data.coef + e.coef;
//如果合起来等于0,则删除掉
if (q->data.coef == 0)
Remove_Polyn(&p, q);//删除掉当前节点
}
}
}
Status ListTraverse(LinkList L, void(*visit)(ElemType))
{ /* 依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败 */
Link p = L.head->next;
int j;
for (j = 1; j <= L.len; j++)
{
visit(p->data);
p = p->next;
}
printf("\b ");
if (L.len == 0)
printf("0");
return OK;
}
void visit(ElemType e)
{
if (e.coef > 0 && e.coef != 1 && e.expn != 0)
{
if (e.expn > 0)
printf("%dx^%d ",e.coef,e.expn);
//printf("+ ");
else
printf("%dx^%d ",e.coef,e.expn);
printf("+ ");
}
else if (e.coef < 0 && e.expn != 0)
{
if (e.expn > 0)
printf("(%d)x^%d",e.coef,e.expn);
//printf("+ ");
else
printf("(%d)x^(%d)",e.coef,e.expn);
printf(" + ");
}
else if (e.coef == 1 && e.expn != 0)
{
if (e.expn > 0)
printf("x^%d",e.expn);
//printf("+");
else
printf("x^(%d)",e.expn);
printf(" + ");
}
else if (e.expn == 0 && e.coef != 0)
printf("%d",e.coef);
else
printf("");
}
Position NextPos(Link p)
{ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置 */
/* 若无后继,则返回NULL */
return p->next;
}
ElemType GetCurElem(Link p)
{ /* 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值 */
return p->data;
}
Status DelFirst(LinkList *L, Link h, Link *q) /* 形参增加L,因为需修改L */
{ /* h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。 */
/* 若链表为空(h指向尾结点),q=NULL,返回FALSE */
*q = h->next;
if (*q) /* 链表非空 */
{
h->next = (*q)->next;
if (!h->next) /* 删除尾结点 */
(*L).tail = h; /* 修改尾指针 */
(*L).len--;
return OK;
}
else
return FALSE; /* 链表空 */
}
void FreeNode(Link *p)
{ /* 释放p所指结点 */
free(*p);
*p = NULL;
}
Status ListEmpty(LinkList L)
{ /* 若线性链表L为空表,则返回TRUE,否则返回FALSE */
if (L.len)
return FALSE;
else
return TRUE;
}
Status Append(LinkList *L, Link s)
{ /* 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的 */
/* 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新 */
/* 的尾结点 */
int i = 1;
(*L).tail->next = s;
while (s->next)
{
s = s->next;
i++;
}
(*L).tail = s;
(*L).len += i;
return OK;
}
void AddPolyn(polynomial &Pa, polynomial &Pb)
{//多项式加法:Pa = Pa+Pb,利用两个多项式的结点构成“和多项式”
Position ha, hb, qa = NULL, qb = NULL;
term a, b;
ha = GetHead(Pa); hb = GetHead(Pb);//ha和hb分别指向Pa和Pb的头结点
if (Pa.len != 0 && Pb.len != 0)
{
qa = NextPos(ha); qb = NextPos(hb);//qa和qb分别指向Pa和Pb中的当前结点
//此时qa和qb都是指向多项式第一项
while (qa && qb)
{//qa和qb非空
a = GetCurElem(qa);
b = GetCurElem(qb); // a和b为两表中当前比较元素
int sum;
switch (cmp(a, b))//比较两者的指数值
{
case -1://多项式中PA中的结点的指数小
ha = qa;
qa = NextPos(ha);
break;
case 0://两者指数值相等
sum = a.coef + b.coef;
if (sum != 0)
{
//修改pa指向的该结点的系数值
qa->data.coef = sum;
//下一个
ha = qa;
}
else
{
//删除结点
DelFirst(&Pa, ha, &qa);
FreeNode(&qa);
}
DelFirst(&Pb, hb, &qb);//也删除掉qb的结点
//都往后移动一位
qb = NextPos(hb);
qa = NextPos(ha);
break;
case 1://多项式PB中的当前结点指数值小
DelFirst(&Pb, hb, &qb);//把当前结点从PB中删除,并用qb指向当前结点用以插入
InsFirst(&Pa, ha, qb);//插入在ha前
qb = NextPos(hb);
qa = NextPos(ha);
break;
}//switch
}//while
if (!ListEmpty(Pb))Append(&Pa, qb);//连接Pb中剩余结点
FreeNode(&hb);//释放Pb的头结点
}//A,B不为空
if (Pa.len == 0)
{
Pa = Pb;//相加结果就是B
}
if (Pb.len == 0)
{
//相加结果就是A
}
//其中一个已经空了
}//AddPolyn
void Opposite(polynomial Pa)
{ // 一元多项式Pa系数取反
Position p;
p = Pa.head;
while (p->next)
{
p = p->next;
p->data.coef *= -1;
}
}
void SubtractPolyn(polynomial &Pa, polynomial &Pb)
{//完成多项式相减运算,即:Pa = Pa-Pb,并销毁一元多项式Pb
Opposite(Pb);
AddPolyn(Pa, Pb);
}
int main()
{
polynomial A, B;
printf("请输入第一个多项式的项数为:");
int length;
scanf("%d",&length);
CreatPolyn(A, length);
//显示A出来
printf("PA(x) = ");
ListTraverse(A, visit);
printf("\n");
//输入B
printf("请输入第二个多项式的项数为:");
scanf("%d",&length);
CreatPolyn(B, length);
//输出B
printf("PB(x) = ");
ListTraverse(B, visit);
printf("\n");
//假设以上输入成功
//进行相减
SubtractPolyn(A, B);
//这时候A是减后的结果
printf("PA(x)-PB(x) = ");
ListTraverse(A, visit);
printf("\n");
return 0;
}
一元多项式相乘
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define LEN sizeof(Poly)
typedef struct term{
float coef; //系数
int expn; //指数
struct term *next;
}Poly,*Link;
int LocateElem(Link p, Link s, Link &q);
void CreatePolyn(Link &p,int m); //创建多项式
void PrintPolyn(Link p); //打印多项式(表示)
int cmp(Link a, Link b);
Link Reverse(Link p); //逆置多项式
Link MultiplyPolyn(Link A,Link B); //多项式相乘
void Calculate(Link p,float x);
int LocateElem(Link p, Link s, Link &q){
/*遍历链表p,每一个结点与s比较指数,
若相同,q指向相同指数项的结点,返回1,
若不相同,根据s所指指数大小在链表p中的位置来确定q的指向结点,返回0
*/
Link p1 = p->next;
Link p2 = p;
while(p1){
if(s->expn > p1->expn){
p1 = p1->next;
p2 = p2->next;
}else if(s->expn == p1->expn){
q = p1;
return 1;
}
else{
q = p2;
return 0;
}
}
if(!p1){
q = p2;
return 0;
}
}
void CreatePolyn(Link &p,int m)
/*创建带头结点的链表(多项式)
且无论按什么顺序输入,或是有相同指数项
最终在多项式中都是升幂顺序!
*/
{
Link s,q;
int i;
p=(Link)malloc(LEN);
p->next=NULL;
for(i=0;i<m;i++)
{
s=(Link)malloc(LEN);
printf("输入系数和指数(以空格隔开):");
scanf("%f %d", &s->coef, &s->expn);
if(!LocateElem(p, s, q)){ //若没有相同指数项,则链入
s->next = q->next;
q->next = s;
}else{ //若有相同指数项,则系数相加
q->coef+=s->coef;
}
}
}
void PrintPolyn(Link p)
//打印显示多项式
{
Link s;
s = p->next;
while(s)
{
printf(" %.2f X^%d", s->coef, s->expn);
s = s->next;
if(s!=NULL)
if(s->coef>=0) printf(" +");
//若下一项系数为正,则打印'+',否则不打印
}
printf("\n");
}
Link Reverse(Link p)
/*用头插法逆置链表,
使多项式由降幂变成升幂顺序
或使多项式由升幂变成降幂顺序
*/
{
Link head=p;
Link q1,q2;
q2=head->next;
head->next=NULL;//断开头结点与第一个结点
while(q2)
{
q1=q2;
q2=q2->next;
q1->next=head->next; //头插
head->next=q1;
}
return head;//返回链表逆置后的头结点
}
Link MultiplyPolyn(Link A,Link B)
/*两个多项式相乘得一个新多项式,并且返回新多项式的头结点的指针
相乘前,A,B两个多项式均是升幂排序
相乘时,A为降幂排序,B为升幂排序
*/
{
Link pa,pb,pc,s,head;
int k,maxExpn,minExpn;
float coef;
head=(Link)malloc(LEN);//头结点
head->next=NULL;
if(A->next!=NULL&&B->next!=NULL){
minExpn=A->next->expn+B->next->expn; //minExpn为两个多项式中指数和的最小值
A=Reverse(A);//将A降幂排列
B=Reverse(B);//将B降幂排列
maxExpn=A->next->expn+B->next->expn; //maxExpn为两个多项式中指数和的最大值
}
else{
return head;
}
pc=head;
B=Reverse(B);//将B升幂排列
for(k = maxExpn;k>=minExpn;k--){ //多项式的乘积指数范围为:minExpn~maxExpn
//根据两项的指数和使每一次循环都得到新多项式中一项
pa = A->next;
while(pa !=NULL&&pa->expn>k){ //找到pa的位置
pa = pa->next;
}
pb = B->next;
while(pb!=NULL&&pa!=NULL&&pa->expn+pb->expn<k){//如果指数和和小于k,pb后移结点
pb = pb->next;
}
coef=0.0;
while(pa!=NULL&&pb!=NULL){
if(pa->expn+pb->expn==k){ //如果指数和等于k,系数和累加,且pa,pb均后移结点
coef+=pa->coef*pb->coef;
pa=pa->next;
pb=pb->next;
}
else if(pa->expn+pb->expn>k){//如果指数和大于k,pb后移结点
pa = pa->next;
}
else{//如果指数和和小于k,pb后移结点
pb = pb->next;
}
}
if(coef!=0.0){
//如果系数和不为0,则生成新结点,将系数和指数赋给新结点后插入到新多项式中
s=(Link)malloc(LEN);
s->coef=coef;
s->expn=k;
s->next=pc->next;
pc->next=s;
pc=s;
}
}
B = Reverse(B);
head=Reverse(head);
return head; //返回新多项式的头结点
}
int main()
{
Link P1,P2,P3; //多项式
int L1,L2; //多项式长度
printf("请输入第一个多项式的项数:");
scanf("%d",&L1);
CreatePolyn(P1,L1);
printf("第一个多项式为:");
printf("P1(X)=");
PrintPolyn(P1);
printf("请输入第二个多项式的项数:");
scanf("%d",&L2);
CreatePolyn(P2,L2);
printf("第二个多项式为:");
printf("P2(X)=");
PrintPolyn(P2);
printf("\n");
printf("两个一元多项式相乘: ");
printf("P1(X)*P2(X)=");
P3=MultiplyPolyn(P1, P2);
PrintPolyn(P3);
return 0;
}