抽象数据类型Polynomial 的实现,多项式的加法、乘法
typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */
/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2
/* ----------------------- 抽象数据类型Polynomial的实现 ------------------------*/
typedef struct /* 项的表示,多项式的项作为LinkList的数据元素 */
{
float coef; /* 系数 */
int expn; /* 指数 */
}term, ElemType;
/* 两个类型名:term用于本ADT,ElemType为LinkList的数据对象名 */
/* ----------------------- 带头结点的线性链表类型存储结构 ------------------------*/
typedef struct LNode /* 结点类型 */
{
ElemType data;
struct LNode *next;
}LNode, *Link, *Position;
typedef struct LinkList /* 链表类型 */
{
Link head, tail; /* 分别指向线性链表中的头结点和最后一个结点 */
int len; /* 指示线性链表中数据元素的个数 */
}LinkList;
typedef LinkList polynomial;
/* -----------------------------------------------------------------------------------------*/
/* -------------------- 需要用到的 具有实用意义的线性链表的基本操作 ---------------------------*/
Status MakeNode(Link *p, ElemType e)
{ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */
*p = (Link)malloc(sizeof(LNode));
if (!*p)
return ERROR;
(*p)->data = e;
return OK;
}
void FreeNode(Link *p)
{ /* 释放p所指结点 */
free(*p);
*p = NULL;
}
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 ClearList(LinkList *L)
{ /* 将线性链表L重置为空表,并释放原链表的结点空间 */
Link p, q;
if ((*L).head != (*L).tail)/* 不是空表 */
{
p = q = (*L).head->next;
(*L).head->next = NULL;
while (p != (*L).tail)
{
p = q->next;
free(q);
q = p;
}
free(q);
(*L).tail = (*L).head;
(*L).len = 0;
}
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;
}
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; /* 链表空 */
}
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;
}
Position PriorPos(LinkList L, Link p)
{ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置 */
/* 若无前驱,则返回NULL */
Link q;
q = L.head->next;
if (q == p) /* 无前驱 */
return NULL;
else
{
while (q->next != p) /* q不是p的直接前驱 */
q = q->next;
return q;
}
}
ElemType GetCurElem(Link p)
{ /* 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值 */
return p->data;
}
Status ListEmpty(LinkList L)
{ /* 若线性链表L为空表,则返回TRUE,否则返回FALSE */
if (L.len)
return FALSE;
else
return TRUE;
}
Position GetHead(LinkList L)
{ /* 返回线性链表L中头结点的位置 */
return L.head;
}
Position NextPos(Link p)
{ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置 */
/* 若无后继,则返回NULL */
return p->next;
}
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 /* 找到 */
{
*q = p;
return TRUE;
}
}
/* ----------------------------------------------------------------------------------------------------------------*/
/* ---------------------- 抽象数据类型Polynomial 基本操作的函数原型说明 -----------------------*/
void CreatPolyn(polynomial *P, int m); /* 算法2.22 */
Status DestroyPolyn(polynomial *P);
void PrintPolyn(polynomial P);
int PolynLength(polynomial P);
void AddPolyn(polynomial *Pa, polynomial *Pb);
void AddPolyn1(polynomial *Pa, polynomial *Pb);
void SubtractPolyn(polynomial *Pa, polynomial *Pb);
void MultiplyPolyn(polynomial *Pa, polynomial *Pb);
/* -----------------------------------------------------------------------------------------------*/
int cmp(term a, term b)
{ /* 依a的指数值<、=或>b的指数值,分别返回-1、0或+1 */
if (a.expn == b.expn)
return 0;
else
return (a.expn - b.expn) / abs(a.expn - b.expn);
}
/* ----------------------------- 抽象数据类型Polynomial 基本操作的实现 -----------------------------*/
void CreatPolyn(polynomial *P, int m) /* 算法2.22 */
{ /* 输入m项的系数和指数,建立表示一元多项式的有序链表P */
Position q, s;
term e;
int i;
InitList(P);
printf("请依次输入%d个系数,指数:\n", m);
for (i = 1; i <= m; ++i)
{ /* 依次输入m个非零项(可按任意顺序) */
scanf_s("%f,%d", &e.coef, &e.expn);
if (!LocateElemP(*P, e, &q, cmp)) /* 当前链表中不存在该指数项,cmp是实参 */
if (MakeNode(&s, e)) /* 生成结点并插入链表 */
InsFirst(P, q, s);
}
}
Status DestroyPolyn(polynomial *P)
{ /* 销毁线性链表L,L不再存在 */
ClearList(P); /* 清空链表 */
FreeNode(&(*P).head);
(*P).tail = NULL;
(*P).len = 0;
return OK;
}
void PrintPolyn(polynomial P)
{ /* 打印输出一元多项式P */
Link q;
q = P.head->next; /* q指向第一个结点 */
printf(" 系数 指数\n");
while (q)
{
printf("%f %d\n", q->data.coef, q->data.expn);
q = q->next;
}
}
int PolynLength(polynomial P)
{ //返回线性链表L中元素个数
return P.len;
}
void AddPolyn(polynomial *Pa, polynomial *Pb) /* 算法2.23 */
{ /* 多项式加法:Pa=Pa+Pb,并销毁一元多项式Pb */
Position ha, hb, qa, qb;
term a, b;
ha = GetHead(*Pa);
hb = GetHead(*Pb); /* ha和hb分别指向Pa和Pb的头结点 */
qa = NextPos(ha);
qb = NextPos(hb); /* qa和qb分别指向Pa和Pb中当前结点(现为第一个结点) */
while (qa && qb)
{ /* qa 和 qb 均为非空 */
a = GetCurElem(qa);
b = GetCurElem(qb); /* a和b为两表中当前比较元素 */
switch (cmp(a, b))
{
case -1:ha = qa; /* 多项式Pa中当前结点的指数值小 */
qa = NextPos(ha); /* ha和qa均向后移一个结点 */
break;
case 0: qa->data.coef += qb->data.coef;
/* 两者的指数值相等,修改Pa当前结点的系数值 */
if (qa->data.coef == 0) /* 删除多项式Pa中当前结点 */
{
DelFirst(Pa, ha, &qa);
FreeNode(&qa);
}
else
ha = qa;
DelFirst(Pb, hb, &qb);
FreeNode(&qb);
qb = NextPos(hb);
qa = NextPos(ha);
break;
case 1: DelFirst(Pb, hb, &qb); /* 多项式Pb中当前结点的指数值小 */
InsFirst(Pa, ha, qb);
ha = ha->next;
qb = NextPos(hb);
}
}
if (!ListEmpty(*Pb))
{
Append(Pa, qb); /* 链接Pb中剩余结点 */
}
DestroyPolyn(Pb); /* 销毁Pb */
}
void AddPolyn1(polynomial *Pa, polynomial *Pb)
{ /* 另一种多项式加法的算法:Pa=Pa+Pb,并销毁一元多项式Pb */
Position qb;
term b;
qb = GetHead(*Pb); /* qb指向Pb的头结点 */
qb = qb->next; /* qb指向Pb的第一个结点 */
while (qb)
{
b = GetCurElem(qb);
OrderInsertMerge(Pa, b, cmp);
qb = qb->next;
}
DestroyPolyn(Pb); /* 销毁Pb */
}
void Opposite(polynomial 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);
}
void MultiplyPolyn(polynomial *Pa, polynomial *Pb)
{ /* 多项式乘法:Pa=PaPb,并销毁一元多项式Pb */
polynomial Pc;
Position qa, qb;
term a, b, c;
InitList(&Pc);
qa = GetHead(*Pa);
qa = qa->next;
while (qa)
{
a = GetCurElem(qa);
qb = GetHead(*Pb);
qb = qb->next;
while (qb)
{
b = GetCurElem(qb);
c.coef = a.coef*b.coef;
c.expn = a.expn + b.expn;
OrderInsertMerge(&Pc, c, cmp);
qb = qb->next;
}
qa = qa->next;
}
DestroyPolyn(Pb); /* 销毁Pb */
ClearList(Pa); /* 将Pa重置为空表 */
(*Pa).head = Pc.head;
(*Pa).tail = Pc.tail;
(*Pa).len = Pc.len;
}
Status OrderInsertMerge(LinkList *L, ElemType e, int(*compare)(term, term))
{ /* 按有序判定函数compare()的约定,将值为e的结点插入或合并到升序链表L的适当位置 */
Position q, s;
if (LocateElemP(*L, e, &q, compare)) /* L中存在该指数项 */
{
q->data.coef += e.coef; /* 改变当前结点系数的值 */
if (!q->data.coef) /* 系数为0 */
{ /* 删除多项式L中当前结点 */
s = PriorPos(*L, q); /* s为当前结点的前驱 */
if (!s) /* q无前驱 */
s = (*L).head;
DelFirst(L, s, &q);
FreeNode(&q);
}
return OK;
}
else /* 生成该指数项并插入链表 */
if (MakeNode(&s, e)) /* 生成结点成功 */
{
InsFirst(L, q, s);
return OK;
}
else /* 生成结点失败 */
return ERROR;
}
/* -------------------------------------------------------------------------------------------------*/
void main()
{
polynomial p, q;
int m;
printf("请输入第一个一元多项式的非零项的个数:");
scanf_s("%d", &m);
CreatPolyn(&p, m);
printf("请输入第二个一元多项式的非零项的个数:");
scanf_s("%d", &m);
CreatPolyn(&q, m);
AddPolyn(&p, &q);
printf("两个一元多项式相加的结果:\n");
PrintPolyn(p);
printf("请输入第三个一元多项式的非零项的个数:");
scanf_s("%d", &m);
CreatPolyn(&q, m);
AddPolyn1(&p, &q);
printf("两个一元多项式相加的结果(另一种方法):\n");
PrintPolyn(p);
printf("请输入第四个一元多项式的非零项的个数:");
scanf_s("%d", &m);
CreatPolyn(&q, m);
SubtractPolyn(&p, &q);
printf("两个一元多项式相减的结果:\n");
PrintPolyn(p);
printf("请输入第五个一元多项式的非零项的个数:");
scanf_s("%d", &m);
CreatPolyn(&q, m);
MultiplyPolyn(&p, &q);
printf("两个一元多项式相乘的结果:\n");
PrintPolyn(p);
DestroyPolyn(&p);
}
运行结果: