数据结构之链表一元多项式的计算

一元多项式的实现与计算

#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

代码下载

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值