您的位置:首页 > 理论基础 > 数据结构算法

数据结构学习笔记 --- 线性表 (一元多项式的表示及相加)

2017-02-22 07:09 567 查看
1. 引言 

本文主要讲解一元多项式的表示及相加。

2. 一元多项式的表示和及相加


/* 一元多项式的表示和相加 */
#include "ds.h"
using namespace std;

#ifdef TEST_LIST
typedef 	int 	 ElemType;
#else
typedef struct {
float 	coef; 	//系数
int 	expn; 	//指数
}term, ElemType;  	// 两个类型名:term用于本ADT,ElemType为LinkList的数据对象名

#endif

typedef struct LNode{
ElemType 		data;
struct LNode	*next;
}LNode, *Link, *Position;

typedef struct {
Link 		head, tail;
int			len;
}LinkList;

#ifndef TEST_LIST
typedef LinkList polynomial;
#define DestroyPolyn DestroyList // 与bo2-6.cpp中的函数同义不同名
#define PolynLength ListLength // 与bo2-6.cpp中的函数同义不同名
#endif

void MakeNode(Link &p, ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s);
// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q);

// 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
void Append(LinkList &L, Link s);
// 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Position PriorPos(LinkList L, Link p);
// 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q);
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
void InsBefore(LinkList &L, Link &p, Link s);

// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
void InsAfter(LinkList &L,Link &p,Link s);
// 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
void SetCurElem(Link p, ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position NextPos(Link p);
Position GetHead(LinkList L);
Position GetLast(LinkList L);
// 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
Status LocatePos(LinkList L, int i, Link &p);
// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));

void ListTraverse(LinkList L, void(*visit)(ElemType) );
// 已知L为有序线性链表,将元素e按非降序插入在L中。
void OrderInsert(LinkList &L, ElemType e, int (*com)(ElemType, ElemType));
// 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType));

void MakeNode(Link &p, ElemType e)
{
p = (Link)malloc(sizeof(LNode));
if (!p)
exit(ERROR);
memcpy(&(p->data), &e, sizeof(ElemType));
p->next = NULL;
}
void FreeNode(Link &p)
{
free(p);
p = NULL;
}

// 带头结点的单链表
void InitList(LinkList &L)
{
Link 	p;
p = (Link)malloc(sizeof(LNode));  //生成头结点
if (p)
{
L.head = L.tail = p;
L.tail->next = NULL;
L.len = 0;
}
else
exit(ERROR);
}
void ClearList(LinkList &L)
{
Link 	q, p = L.head->next;

if (0 == L.len)
return;

L.head->next = NULL;
while (p)
{
q = p->next;
free(p);
p = q;
}

L.tail = L.head;
L.len = 0;
}
void DestroyList(LinkList &L)
{
ClearList(L);
FreeNode(L.head);
L.tail = NULL;
L.len = 0;
}
// h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前, 形参增加L,因为需修改L
void InsFirst(LinkList &L,Link h,Link s)
{
s->next = h->next;
h->next = s;
if (h == L.tail)
L.tail = h->next;
L.len++;
}
// h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
// 若链表为空(h指向尾结点),q=NULL,返回FALSE
Status DelFirst(LinkList &L, Link h, Link &q)
{
#if 0
q = h->next;
if (h == L.tail)
return FALSE;

h->next = q->next;
if (!q->next)
L.tail = h;

L.len--;
return OK;
#endif
q=h->next;
if(q) // 链表非空
{
h->next=q->next;
if(!h->next) // 删除尾结点
L.tail=h; // 修改尾指针
L.len--;
return OK;
}
else
return FALSE; // 链表空
}

// 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
// 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
void Append(LinkList &L, Link s)
{
int 	i = 1;

L.tail->next = s;

if (NULL == s)
return;

while (s->next)
{
s = s->next;
i++;
}

L.tail = s;
L.len += i;
}
// 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
Position PriorPos(LinkList L, Link p)
{
Link 	q = L.head->next;

if (!L.len || 1 == L.len)
return NULL;

while (q->next && q->next != p)
{
q = q->next;
}

if (!q->next)
return NULL;

return q;
}

// 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
Status Remove(LinkList &L, Link &q)
{
Link 	p = L.head;
q = L.tail;

if (!L.len)
{
q = NULL;
return ERROR;
}
while (p->next != L.tail)
{
p = p->next;
}

p->next = NULL;
L.tail = p;

L.len--;
return OK;
}
// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
// 并修改指针p指向新插入的结点
void InsBefore(LinkList &L, Link &p, Link s)
{
Link 	pp = L.head;

while (pp->next && pp->next != p)
pp = pp->next;

if (pp->next)
{
s->next = pp->next;
pp->next = s;
}
else
return;
p = s;
L.len++;
}

// 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
// 并修改指针p指向新插入的结点
void InsAfter(LinkList &L,Link &p,Link s)
{
if (p == L.tail)
{
s->next = p->next;
p->next = s;
L.tail = s;
}
else
{
s->next = p->next;
p->next = s;
}

p = s;
L.len++;
}
// 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
void SetCurElem(Link p, ElemType e)
{
memcpy(&(p->data), &e, sizeof(ElemType));
}
ElemType GetCurElem(Link p)
{
return p->data;
}
Status ListEmpty(LinkList L)
{
if (L.len)
return FALSE;
else
return TRUE;

}
int ListLength(LinkList L)
{
return L.len;
}
Position GetHead(LinkList L)
{
return L.head;
}
Position GetLast(LinkList L)
{
return L.tail;
}
Position NextPos(Link p)
{
return p->next;
}
// 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
Status LocatePos(LinkList L, int i, Link &p)
{
int 	j = 0;

if (i < 0 || i > L.len)
return ERROR;
p = L.head;
for (; j < i; j++)
p = p->next;

return OK;
}

// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
// 若不存在这样的元素,则返回NULL
Position LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{
Link 		p = L.head->next;

while (p && !compare(e, p->data))
p = p->next;

if (!p)
return NULL;

return p;
}

void ListTraverse(LinkList L, void(*visit)(ElemType) )
{
Link 	p = L.head->next;

while (p)
{
visit(p->data);
p = p->next;
}
printf("\n");
}

// 已知L为有序线性链表,将元素e按非降序插入在L中。
void OrderInsert(LinkList &L, ElemType e, int (*comp)(ElemType, ElemType))
{
#if 1
Link 	q = L.head, s;
Link 	p = q->next;

MakeNode(s, e);

while (p && comp(p->data, e) < 0) // p不是表尾且元素值小于e
{
q = p;
p = p->next;
}

q->next = s;
s->next = p;

if (!p)  // 插在表尾
L.tail = s;  // 修改尾结点

L.len++;
#else
Link o,p,q;
q=L.head;
p=q->next;
while(p!=NULL&&comp(p->data,e)<0) // p不是表尾且元素值小于e
{
q=p;
p=p->next;
}
o=(Link)malloc(sizeof(LNode)); // 生成结点
o->data=e; // 赋值
q->next=o; // 插入
o->next=p;
L.len++; // 表长加1
if(!p) // 插在表尾
L.tail=o; // 修改尾结点
#endif
}
// 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
// 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
// compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
Status LocateElem(LinkList L,ElemType e,Position &q,int(*compare)(ElemType,ElemType))
{
Link 	p = L.head;

do
{
q = p;
p = p->next;
}while (p && compare(p->data, e) < 0);

if (p && compare(p->data, e) == 0)
{
q = p;
return TRUE;
}
else
{
return FALSE;
}
}

#ifdef TEST_LIST
void print(ElemType e)
{
printf("%d ", e);
}

int comp(ElemType a, ElemType b)
{
return a-b;
}

Status equal(ElemType c1,ElemType c2)
{ // 判断是否相等的函数
if(c1==c2)
return TRUE;
else
return FALSE;
}
#else

void PrintPolyn(polynomial P)
{ // 打印输出一元多项式P
Link q;
q=P.head->next; // q指向第1个结点
printf("  系数    指数\n");
while(q)
{
printf("%f  %d\n",q->data.coef,q->data.expn);
q=q->next;
}
}

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);
}

#endif

void OrderInsertMerge(LinkList &L,ElemType e,int(* compare)(term,term))
{ // 按有序判定函数compare()的约定,将值为e的结点插入或合并到升序链表L的适当位置
Position q,s;
if(LocateElem(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);
}
}
else // 生成该指数项并插入链表
{
MakeNode(s,e); // 生成结点
InsFirst(L,q,s);
}
}

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("%f,%d",&e.coef,&e.expn);
if(!LocateElem(P,e,q,cmp)) // 当前链表中不存在该指数项,cmp是实参
{
MakeNode(s,e); // 生成结点并插入链表
InsFirst(P,q,s);
}
}
}

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中当前结点(现为第1个结点)
while(!ListEmpty(Pa)&&!ListEmpty(Pb)&&qa)
{ // Pa和Pb均非空且ha没指向尾结点(qa!=0)
a=GetCurElem(qa);
b=GetCurElem(qb); // a和b为两表中当前比较元素
switch(cmp(a,b))
{
case -1:ha=qa; // 多项式Pa中当前结点的指数值小
qa=NextPos(ha); // ha和qa均向后移1个结点
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))
{
qa = qb;
Pb.tail=hb;
Append(Pa,qa); // 链接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的第1个结点
while(qb)
{
b=GetCurElem(qb);
OrderInsertMerge(Pa,b,cmp);
qb=qb->next;
}
DestroyPolyn(Pb); // 销毁Pb
}

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);
AddPolyn1(Pa,Pb);
}

void MultiplyPolyn(polynomial &Pa,polynomial &Pb)
{ // 多项式乘法:Pa=Pa×Pb,并销毁一元多项式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;
}

#ifdef TEST_LIST
int main()
{
Link p,h;
LinkList L;
Status i;
int j,k;
InitList(L); // 初始化空的线性表L
for(j=1;j<=2;j++)
{
MakeNode(p,j); // 生成由p指向、值为j的结点
InsFirst(L,L.tail,p); // 插在表尾
}
ListTraverse(L,print); // 输出L
cout << "L'length:"<< ListLength(L) << endl;

OrderInsert(L,0,comp); // 按升序插在有序表头

ListTraverse(L,print); // 输出L
cout << "L'length:"<< ListLength(L) << endl;
for(j=0;j<=3;j++)
{
i=LocateElem(L,j,p,comp);
if(i)
printf("链表中有值为%d的元素。\n",p->data);
else
printf("链表中没有值为%d的元素。\n",j);
}
printf("输出链表:");
ListTraverse(L,print); // 输出L
cout << "L'length:"<< ListLength(L) << endl;
for(j=1;j<=4;j++)
{
printf("删除表头结点:");
DelFirst(L,L.head,p); // 删除L的首结点,并以p返回
if(p)
printf("%d\n",GetCurElem(p));
else
printf("表空,无法删除 p=%u\n",p);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
MakeNode(p,10);
p->next=NULL; // 尾结点
for(j=4;j>=1;j--)
{
MakeNode(h,j*2);
h->next=p;
p=h;
} // h指向一串5个结点,其值依次是2 4 6 8 10
Append(L,h); // 把结点h链接在线性链表L的最后一个结点之后
OrderInsert(L,12,comp); // 按升序插在有序表尾头
OrderInsert(L,7,comp); // 按升序插在有序表中间
printf("输出链表:");
ListTraverse(L,print); // 输出L
for(j=1;j<=2;j++)
{
p=LocateElem(L,j*5,equal);
if(p)
printf("L中存在值为%d的结点。\n",j*5);
else
printf("L中不存在值为%d的结点。\n",j*5);
}
for(j=1;j<=2;j++)
{
LocatePos(L,j,p); // p指向L的第j个结点
h=PriorPos(L,p); // h指向p的前驱
if(h)
printf("%d的前驱是%d。\n",p->data,h->data);
else
printf("%d没前驱。\n",p->data);
}
k=ListLength(L);
for(j=k-1;j<=k;j++)
{
LocatePos(L,j,p); // p指向L的第j个结点
h=NextPos(p); // h指向p的后继
if(h)
printf("%d的后继是%d。\n",p->data,h->data);
else
printf("%d没后继。\n",p->data);
}
printf("L中结点个数=%d L是否空 %d(1:空 0:否)\n",ListLength(L),ListEmpty(L));
p=GetLast(L); // p指向最后一个结点
SetCurElem(p,15); // 将最后一个结点的值变为15
printf("第1个元素为%d 最后1个元素为%d\n",GetCurElem(GetHead(L)->next),GetCurElem(p));
MakeNode(h,10);
InsBefore(L,p,h); // 将10插到尾结点之前,p指向新结点
p=p->next; // p恢复为尾结点
MakeNode(h,20);
InsAfter(L,p,h); // 将20插到尾结点之后
k=ListLength(L);
printf("依次删除表尾结点并输出其值:");
for(j=0;j<=k;j++)
if(!(i=Remove(L,p))) // 删除不成功
printf("删除不成功 p=%u\n",p);
else
printf("%d ",p->data);
MakeNode(p,29); // 重建具有1个结点(29)的链表
InsFirst(L,L.head,p);
DestroyList(L); // 销毁线性链表L
printf("销毁线性链表L之后: L.head=%u L.tail=%u L.len=%d\n",L.head,L.tail,L.len);
}
#else

int main()
{
polynomial p,q;
int m;
printf("请输入第1个一元多项式的非零项的个数:");
scanf("%d",&m);
CreatPolyn(p,m);
printf("请输入第2个一元多项式的非零项的个数:");
scanf("%d",&m);
CreatPolyn(q,m);
AddPolyn(p,q);
//SubtractPolyn(p,q);
printf("2个一元多项式相加的结果:\n");
PrintPolyn(p);

printf("请输入第3个一元多项式的非零项的个数:");
scanf("%d",&m);
CreatPolyn(q,m);
AddPolyn1(p,q);
printf("2个一元多项式相加的结果(另一种方法):\n");
PrintPolyn(p);
printf("请输入第4个一元多项式的非零项的个数:");
scanf("%d",&m);
CreatPolyn(q,m);
SubtractPolyn(p,q);
printf("2个一元多项式相减的结果:\n");
PrintPolyn(p);
printf("请输入第5个一元多项式的非零项的个数:");
scanf("%d",&m);
CreatPolyn(q,m);
MultiplyPolyn(p,q);
printf("2个一元多项式相乘的结果:\n");
PrintPolyn(p);
DestroyPolyn(p);

}

#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐