一元多项式的实现与计算
#pragma once
#include <string>
#include <stdbool.h>
//复数的存储结构
typedef struct {
double coef;
int expn;
}Item;
//结点
typedef struct node{
Item item;
struct node * next;
}Node;
//Polynomial结构包含指向头结点的指针,元素数目和名称
typedef struct {
Node * head;
int counts;
std::string string;
}Polynmail;
//用于查询元素和删除Polynmail
typedef struct {
Node * front;
Node * behind;
}Pair;
//初始化Polynmail
void InitPolynmail(Polynmail & P);
//判断链表中有没有元素
bool PolynmailEmpty(Polynmail P);
//创建一个Polynmail,有n项
void CreatePolynmail(Polynmail & P, int n);
//销毁一个Polynmail
bool DestroyPolynmail(Polynmail & P);
//查询item元素在P中的位置,pair中的前后指针分别指向目标元素和其上一个元素,返回true
//如item不在P中,pair分别指向第一个比item大的元素和其上一个,pcompare是比较函数指针,返回false
bool LocateItem(Polynmail P, Pair & pair, Item item, int(*pcompare)(Item item_a, Item item_b));
//将pnode根据pair中的位置插入到P中
bool InsertItem(Polynmail & P, Pair & pair, Node * pnode);
//打印P
int PrintPolynmail(Polynmail P);
//求两个多项式的和结果放在PA中
int AddPoylnmail(Polynmail & PA,Polynmail & PB);
//求减
int SubtractPolynmail(Polynmail & PA, Polynmail & PB);
//求乘积
int Multiplypolynmail(Polynmail & PA, Polynmail & PB);
#include <iostream>
#include "polynmail.h"
//通过指数expn,比较两项的大小,return item_a.expn - item_b.expn
int Compare(Item item_a, Item item_b);
//初始化
void InitPolynmail(Polynmail & P)
{
P.head = nullptr;
P.counts = 0;
P.string = 'P';
}
//判断有没有实际元素
bool PolynmailEmpty(Polynmail P)
{
return !(P.head->next);
}
//创建Polynmail对象时通过LocateItem函数找到输入的每一项应该插入的位置
//最终得到按指数递减顺序的P(创建P时无序输入)
bool LocateItem(Polynmail P, Pair & pair, Item item, int(*pcompare)(Item item_a, Item item_b))
{
//pair.front和pair.behind分别指向P的第一个元素和P的头结点(头结点不存元素)
pair.front = P.head->next;
pair.behind = P.head;
//循环找到第一个不小于item的结点 或NULL(没有比item大的)
for (;pair.front && (*pcompare)(item, pair.front->item) > 0; )
{
pair.behind = pair.front;
pair.front = pair.front->next;
}
//如果找到等于item的结点返回true否则false
if (pair.front)
{
if ((*pcompare)(item, pair.front->item) == 0)
return true;
else
return false;
}
else
return false;
}
//根据pair的位置插入pnode,元素数目加一
bool InsertItem(Polynmail & P, Pair & pair, Node * pnode)
{
if (!pair.behind)
return false;
pair.behind->next = pnode;
pnode->next = pair.front;
P.counts++;
return true;
}
//输入P的名字然后输入n项表达式
void CreatePolynmail(Polynmail & P, int n)
{
int i;
Node * pnew;
Pair pair = {nullptr,nullptr};
//首先创建一个头结点,不存实际数据
if (!(pnew = (Node *)new Node))
exit(1);
pnew->item.coef = 0.0;
pnew->item.expn = -1;
P.head = pnew;
P.head->next = nullptr;
std::cin >> P.string; //输入名字
for (i = 0;i < n;i++)
{
if (!(pnew = (Node *)new Node)) exit(1); //创建结点输入数据
std::cin >> pnew->item.coef >> pnew->item.expn;
pnew->next = nullptr;
if (!pnew->item.coef || LocateItem(P, pair, pnew->item, Compare)) //系数为0或此指数项已经存在就重新输入
{
std::cout << "由于x的" << pnew->item.expn << "次方项已存在或系数为0,请重新输入;" << std::endl;
i--;
}
else
InsertItem(P, pair, pnew); //找到位置,添加结点
}
while (std::cin.get() != '\n')
continue;
}
bool DestroyPolynmail(Polynmail & P)
{
if (!P.head) //是否为空P
return true;
Pair pair;
//pair.front指向下一个结点,pair.behind释放当前结点,循环至pair.front为nullptr
pair.front = P.head->next;
pair.behind = P.head;
P.head = nullptr;
P.counts = 0;
while (pair.front)
{
delete pair.behind;
pair.behind = pair.front;
pair.front = pair.front->next;
}
delete pair.behind; //pair.front 为nullptr时还剩最后一个结点没释放
pair.behind = nullptr;
return true;
}
int PrintPolynmail(Polynmail P)
{
if (PolynmailEmpty(P)) //没有可打印的元素则返回错误1
return 1;
int i, n;
Node * pnode;
n = P.counts-1; //首先打印名字和第一项,剩下的n-1项要求系数都显示正负号
pnode = P.head->next;
std::cout << P.string << "(x)=";
std::cout << pnode->item.coef << "x^" << pnode->item.expn;
pnode = pnode->next;
for (i = 0;i < n;i++)
{
std::cout<<std::showpos<< pnode->item.coef << "x^" <<std::noshowpos<< pnode->item.expn;
pnode = pnode->next;
}
return 0;
}
//PA和PB都是按指数递减。两多项式相加,按顺序分别比较每一项按递减顺序串联到PA中,PB变为只带头结点的零项
int AddPoylnmail(Polynmail & PA, Polynmail & PB)
{
if (PolynmailEmpty(PA) || PolynmailEmpty(PB))
return 1;
int i,n=0;
Node *pa, *pb,*pc,*pd;
pa = PA.head->next; //pa,pb分别指向PA,PB的第一项,pc指向PA的头结点
pb = PB.head->next;
pc = PA.head;
pd = nullptr;
while (pa && pb)
{
i = Compare(pa->item, pb->item); //比较指数大小
if (i > 0) i = 1;
else if (i < 0) i = -1; //改变i的值方便使用switch语法
else i = 0;
switch (i)
{
case -1: //pa所指元素小于pb,pc指向的结点连向pa所指的结点
pc->next = pa; pa = pa->next; pc = pc->next;break; //pa指向PA的下一个结点,pc总是指向合并的最后一个结点,用以连接下一个结点
case 0:
if (pa->item.coef += pb->item.coef)
{ //pa,pb所指两项指数相等,将系数相加
pc->next = pa; //系数不为0则pc指向系数相加以后pa指向的结点,释放pb所指结点
pc = pc->next; //系数为0,释放pa,pb所指结点
pa = pa->next;
pd = pb;
pb = pb->next;
delete pd;
n++;
}
else
{
pd = pa; pa = pa->next; delete pd;
pd = pb; pb = pb->next; delete pd;
n += 2;
}
break;
case 1: //pa指向元素比pb大,pc=pb,pb指向下一个结点,pc更新位置
pc->next = pb; pb = pb->next; pc = pc->next;break;
default:
break;
}
}
if (pa) //如果pa或者pb还有剩余结点,将剩余结点并入PA最后
pc->next = pa;
else
pc->next = pb;
PA.counts = PA.counts + PB.counts - n; //更新PA的元素数目
PA.string = "Padd"; //改名
PB.head->next =nullptr; //PB只剩一个头结点
return 0;
}
//原理同上,多一步将PB所有项的系数取反
int SubtractPolynmail(Polynmail & PA, Polynmail & PB)
{
if (PolynmailEmpty(PA) || PolynmailEmpty(PB))
return 1;
int i,n=0;
Node *pa, *pb, *pc, *pd;
pd = PB.head->next;
while (pd)
{
pd->item.coef = (-pd->item.coef);
pd = pd->next;
}
pa = PA.head->next;
pb = PB.head->next;
pc = PA.head;
pd = nullptr;
while (pa && pb)
{
i = Compare(pa->item, pb->item);
if (i > 0) i = 1;
else if (i < 0) i = -1;
else i = 0;
switch (i)
{
case -1:
pc->next = pa; pa = pa->next; pc = pc->next;break;
case 0:
if (pa->item.coef += pb->item.coef)
{
pc->next = pa;
pc = pc->next;
pa = pa->next;
pd = pb;
pb = pb->next;
delete pd;
n++;
}
else
{
pd = pa; pa = pa->next; delete pd;
pd = pb; pb = pb->next; delete pd;
n += 2;
}
break;
case 1:
pc->next = pb; pb = pb->next; pc = pc->next;break;
default:
break;
}
}
if (pa)
pc->next = pa;
else
pc->next = pb;
PA.counts = PA.counts + PB.counts - n;
PA.string = "Psub";
PB.head->next = nullptr;
return 0;
}
int Multiplypolynmail(Polynmail & PA, Polynmail & PB)
{
if (PolynmailEmpty(PA) || PolynmailEmpty(PB))
return 1;
int i,n;
const int COUNTS=PA.counts; //PA中项数
Node *pnew, *pa,*pb,*pc,*pd;
Polynmail PC,PD; //一个备份一个中间链表
InitPolynmail(PC);
InitPolynmail(PD);
PD.counts = COUNTS;
pb = pd=nullptr;
n =COUNTS; //创建一个和PA一样的多项式PC
if (!(pnew = (Node *)new Node)) exit(1);
pnew->next = nullptr;
pnew->item = PA.head->item;
PC.head = pnew;
pc = pnew;
pa = PA.head->next;
for (i = 0;i < n;i++)
{
if (!(pnew = (Node *)new Node)) exit(1);
pnew->next = nullptr;
pnew->item = pa->item;
pc->next = pnew;
pc = pnew;
pa = pa->next;
}
//先把PB的第一项和PA相乘,之后PB的每一项和PC相乘的结果创建一个PD(不改变PC)
pb = PB.head->next;
pa = PA.head->next;
while (pa)
{
pa->item.coef *= pb->item.coef;
pa->item.expn += pb->item.expn;
pa = pa->next;
}
pb = pb->next; //PB的下一项
if (!(pnew = (Node *)new Node)) exit(1); //先给PD创建一个头结点,之后与PA相加头结点一直存在
pnew->next = nullptr;
pd = pnew;
PD.head = pnew;
PD.head->item = PA.head->item;
while (pb)
{
pc = PC.head->next;
pd = PD.head;
while (pc) //PB一项和PC乘积的结果创建PD
{
if (!(pnew = (Node *)new Node)) exit(1); //创建结点
pnew->next = nullptr;
pnew->item.coef=pc->item.coef*pb->item.coef; //结果赋值
pnew->item.expn = pc->item.expn + pb->item.expn;
pd->next = pnew;
pd = pnew;
pc = pc->next;
}
AddPoylnmail(PA, PD); //PA和PD相加,PD只剩头结点
pb = pb->next;
}
PA.string = "Pmul"; //改名,释放PC和PD
DestroyPolynmail(PC);
DestroyPolynmail(PD);
return 0;
}
#include <iostream>
#include "polynmail.h"
//测试加减乘三个函数 (P1+P2)*(P3-PA)
int main()
{
Polynmail P1, P2, P3, P4;
//初始化
InitPolynmail(P1);
InitPolynmail(P2);
InitPolynmail(P3);
InitPolynmail(P4);
//创建
CreatePolynmail(P1, 1);
CreatePolynmail(P2, 2);
CreatePolynmail(P3, 3);
CreatePolynmail(P4, 4);
PrintPolynmail(P1);
std::cout << std::endl;
PrintPolynmail(P2);
std::cout << std::endl;
PrintPolynmail(P3);
std::cout << std::endl;
PrintPolynmail(P4);
std::cout << std::endl;
AddPoylnmail(P1, P2);
PrintPolynmail(P1);
std::cout << std::endl;
SubtractPolynmail(P3, P4);
PrintPolynmail(P3);
std::cout << std::endl;
Multiplypolynmail(P1, P3);
PrintPolynmail(P1);
std::cout << std::endl;
DestroyPolynmail(P1);
DestroyPolynmail(P2);
DestroyPolynmail(P3);
DestroyPolynmail(P4);
return 0;
}
http://download.csdn.net/detail/biqigu/9620924
代码下载