一元多项式的相除操作(链表)

一元多项式的除法运算如何实现,要求多项式采用链表存储结构,不必利用比对两个多项式的公因式的方法将分式化为最简形式,建议采用综合除法。

        这个题目原来是要求利用寻找公因式的方法将分式化为最简形式,但是呢,由于求解高次多项式的因式的操作涉及解方程的操作,而方程又不一定有实数范围内的实根,就算有也不一定是整数根,此类种种会导致用计算机实现一元多项式的除法操作异常地耗时、困难,所以以我个人的能力只能利用综合除法实现一元多项式的除法操作。至于其它各种用于一元多项式除法的方法,我上传到了自己的文档中(未用计算机程序实现,单纯的数学讨论),很建议大家去看看。

综合除法是什么呢?

综合除法(synthetic division)是一种简便的除法,只通过乘、加两种运算便可计算到一元多项式除以(x - a)的商式与余式。

-->综合除法<--

例如求取 a(x) = x^5 + x^3 - x^2 + 1与 b(x) = x^4 + x^2 的商,最终可以得到 c(x) = a(x)/b(x) = x -  (x^2 - 1)/(x^4 + x^2) ,其中 - (x^2 - 1)/(x^4 + x^2) 就是商式,x 就是余式。

        现在我编写了一段代码:

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#include<math.h>
typedef struct poly
{
	char sign;//符号
	int coef;//系数
	char alph;//字母
	int exp;//指数
	struct poly *next;
}poly;
poly *detach(poly *head)
{
	poly *temp = NULL;
	poly *pre = head;
	while (head->coef == 0)
	{
		if (head->next == NULL)//队尾结点
			break;
		head = head->next;
		free(pre);
		pre = head;
	}
	temp = head->next;
	pre = head;//开头的系数即为0//去掉pre=head;//不能去掉pre=head;,此head非彼head
	while (temp != NULL)
	{
		while (temp->coef == 0)
		{
			temp = temp->next;
			free(pre->next);
			if (temp != NULL)//
				pre->next = temp;
			else
			{
				pre->next = NULL;
				return head;//使用break;只能跳出内层循环,而我们要做的就是结束程序
			}
		}
		pre = temp;
		temp = temp->next;//
	}
	return head;
}
void disappear(poly *head)
{
	poly *temp = head->next;
	while (temp != NULL)
	{
		free(head);
		head = temp;
		temp = temp->next;
	}
	free(head);
	printf("Free all nodes successfully.\n");
}
int flag = 0;
char line1[40];
poly *input(poly* head)
{
	poly *new = head;
	poly *temp = NULL;
	char coef[4];
	char exp[4];
	int cnt = 0;
	char line[40];
	FILE *fp = fopen("D:\\main1.txt", "r");
	if (flag == 1)
		strcpy(line, line1);
	else
	{
		fscanf(fp, "%s", line);
		fscanf(fp, "%s", line1);
		flag++;
	}
	strcpy(line, line + 5);
	int line_cnt = 0;
	while (1)
	{
		if (isdigit(line[line_cnt]) || isalpha(line[line_cnt]))
			new->sign = '+';
		else
			new->sign = line[line_cnt++];//结点符号
		if (isdigit(line[line_cnt]))
		{
			while (isdigit(line[line_cnt]))
				coef[cnt++] = line[line_cnt++];
			coef[cnt] = '\0';
			new->coef = atoi(coef);
			cnt = 0;
			if (line[line_cnt] == '\0')//if (line[line_cnt] == '\n')是错的,常数项
			{
				new->exp = 0;
				new->alph = head->alph;
				new->next = NULL;
				break;
			}
		}//结点系数
		else
			new->coef = 1;//系数为1
		new->alph = line[line_cnt];//结点字母
		if (line[line_cnt + 1] == '^')
		{
			line_cnt += 2;//省略'^'
			while (isdigit(line[line_cnt]))
				exp[cnt++] = line[line_cnt++];
			exp[cnt] = '\0';
			new->exp = atoi(exp);//结点指数
			cnt = 0;
			strcpy(exp, "\0");
		}
		else
		{
			new->exp = 1;
			line_cnt++;
		}

		if (line[line_cnt] == '\0')//if (line[line_cnt] == '\n')是错的
		{
			new->next = NULL;
			break;
		}
		else
		{
			temp = new;
			new = (poly*)malloc(sizeof(poly));
			temp->next = new;
		}
	}
	fclose(fp);
	return head;
}
void output(poly* head, FILE *fp)
{
	poly *temp_ptr = head;
	while (temp_ptr != NULL)
	{
		if (temp_ptr->sign == '-' || temp_ptr != head)
		{
			fprintf(fp, "%c", temp_ptr->sign);
		}
		if (temp_ptr->coef != 1 || temp_ptr->exp == 0)
			fprintf(fp, "%d", temp_ptr->coef);
		if (temp_ptr->exp != 0 && temp_ptr->exp != 1)
		{
			fprintf(fp, "%c^", temp_ptr->alph);
			fprintf(fp, "%d", temp_ptr->exp);
		}
		else if (temp_ptr->exp == 1)
			fprintf(fp, "%c", temp_ptr->alph);
		temp_ptr = temp_ptr->next;
	}
}
void trim(poly *node)
{//将结构体的符号数据域中的符号并入到系数数据域
	node->coef = node->sign == '+' ? node->coef : -node->coef;
}
void regain(poly *node)
{//将结构体的系数数据域中的符号归还到符号数据域
	node->sign = node->coef < 0 ? '-' : '+';
	node->coef = abs(node->coef);
}
int number(poly *head)
{
	int num = 0;
	while (head != NULL)
	{
		num++;
		//printf("\t%dhead:%p\n",num, head);
		head = head->next;

	}
	return num;
}
poly *attain(poly *head, int number)
{
	int num = -1;
	poly *head_temp = head;
	while (head_temp != NULL)
	{
		num++;
		head_temp = head_temp->next;
	}
	if (number > num)
		return NULL;
	else
	{
		num = 0;
		while (num < number)
		{
			head = head->next;
			num++;
		}
		return head;
	}
}
void node_multiple(poly *node1, poly *node2)
{
	node1->sign = node1->sign == node2->sign ? '+' : '-';
	node1->coef = node1->coef*node2->coef;
	node1->exp = node1->exp + node2->exp;
}
void node_copy(poly *node1, poly *node2)
{
	node1->sign = node2->sign;
	node1->coef = node2->coef;
	node1->alph = node2->alph;
	node1->exp = node2->exp;
}
int cnt = 0;
void devision(poly *head1, poly *head2, FILE *fp)
{
	/*
	printf("\n");
	output(head2, stdout);
	printf("\n");*/
	poly *head6 = (poly*)malloc(sizeof(poly));
	poly *befo = NULL;
	poly *temp1 = head1;
	poly *temp2 = head2;
	poly *node = NULL;
	//output(temp1, stdout);
	//printf("\n");
	while (temp1 != NULL && abs(temp1->coef) < abs(head2->coef) && temp1->exp\
		>= head2->exp)
		temp1 = temp1->next;
	//output(temp1, stdout);
	if (temp1 != NULL && abs(temp1->coef) >= abs(head2->coef) && temp1->exp\
		>= head2->exp)
	{
		//output(temp1, stdout);
		trim(temp1);
		trim(head2);//变为非正常形式
		head6->sign = temp1->coef * head2->coef > 0 ? '+' : '-';
		head6->coef = abs(temp1->coef / head2->coef);
		head6->alph = temp1->alph;
		head6->exp = temp1->exp - head2->exp;
		temp1->coef = temp1->coef - temp1->coef / head2->coef*head2->coef;
		head6->next = NULL;//正常形式

		if (cnt != 0 && head6->sign == '+')
			fputc('+', fp);
		else
			cnt = 1;
		output(head6, fp);
		regain(temp1);
		regain(head2);//恢复正常形式

		for (int i = 1; i < number(head2); i++)
		{
			node = (poly*)malloc(sizeof(poly));
			node_copy(node, attain(head2, i));
			node_multiple(node, head6);//用到了head6
			for (int j = 0; j < number(head1); j++)
			{
				if (node->exp == attain(head1, j)->exp)
				{
					trim(attain(head1, j));
					trim(node);
					attain(head1, j)->coef = attain(head1, j)->coef - node->coef;
					regain(attain(head1, j));
					free(node);
					break;
				}
				else if (attain(head1, j + 1) != NULL && \
					node->exp > attain(head1, j + 1)->exp)
				{
					node->next = attain(head1, j + 1);
					attain(head1, j)->next = node;
					node->sign = node->sign == '+' ? '-' : '+';
					break;
				}
				else if (attain(head1, j + 1) == NULL)
				{
					attain(head1, j)->next = node;
					node->next = NULL;
					node->sign = node->sign == '+' ? '-' : '+';
					break;
				}
			}
		}
		if (head1->next != NULL && head1->coef == 0)
		{
			befo = head1;
			head1 = head1->next;
			free(befo);
		}
		head1 = detach(head1);
		devision(head1, head2, fp);
	}
	else
	{
		temp1 = head1;
		if (head1->coef != 0)
		{
			if (head1->sign == head2->sign)
			{
				if (head1->sign == '-')
				{
					while (temp1 != NULL)
					{
						temp1->sign = temp1->sign == '-' ? '+' : '-';
						temp1 = temp1->next;
					}
					while (temp2 != NULL)
					{
						temp2->sign = temp2->sign == '-' ? '+' : '-';
						temp2 = temp2->next;
					}
				}
				fputc('+', fp);
			}
			else if (head1->sign != head2->sign)
			{
				if (head1->sign == '+')
					while (temp2 != NULL)
					{
						temp2->sign = temp2->sign == '-' ? '+' : '-';
						temp2 = temp2->next;
					}
				else
					while (temp1 != NULL)
					{
						temp1->sign = temp1->sign == '-' ? '+' : '-';
						temp1 = temp1->next;
					}
				fputc('-', fp);
			}

			if (head1->next != NULL)
			{
				fputc('(', fp);
				output(head1, fp);
				fputc(')', fp);
			}
			else
				output(head1, fp);
			if (head2->next != NULL)
			{
				fprintf(fp, "/(");
				output(head2, fp);
				fputc(')', fp);
				fputc('\n', fp);
			}
			else
			{
				fputc('/', fp);
				output(head2, fp);
				fputc('\n', fp);
			}
		}
	}
}
int main()
{
	poly *head1 = (poly*)malloc(sizeof(poly));
	poly *head2 = (poly*)malloc(sizeof(poly));
	FILE *fp = NULL;
	input(head1);
	input(head2);
	fp = fopen("D:\\main2.txt", "w");
	if (head1->coef == 0 && head2->coef != 0)
	{
		fprintf(fp, "c(x)=0\n");
		return 0;
	}
	else if (head2->coef == 0)
	{
		fprintf(fp, "Devision Error:denominator can't be zero.\n");
		return 0;
	}
	fprintf(fp, "c(x)=");
	if (abs(head1->coef) >= abs(head2->coef) && head1->exp >= head2->exp)
		devision(head1, head2, fp);
	else
		devision(head2, head1, fp);
	fclose(fp);
	return 0;
}

        同一元多项式的加、减、乘法一样在建立起代表两个多项式的链表后,我们对链表进行相应处理达到一元多项式的除法效果。首先,作为分母的多项式不能为0,否则抛出异常;若分子为0,那么直接输出为0。在这两种情况都不满足时,将这两个多项式传递给 devision() 函数进行除法运算。

        如果第一个多项式首项的系数小于或不能整除第二个多项式首项的系数,或者第一个多项式首项的指数小于第二个多项式首项的指数,又或是第一个多项式的项数少于第二个多项式的项数那么直接输出这两个多项式的商。

       否则,进入下一个步骤,将第一个多项式首项除以第二个多项式首项得到的商存入 head6 结点中,将该值打印出来。之后将该值依次与第二个多项式中除第一个项外的各个项相乘然后用第一个多项式减去这些单项式的值,然后将得到的新的第一条链表继续通过递归传递给下个过程,第二条链表保持原样,最终我们得到的就是两个多项式的商。

        这段代码会从D盘中的文件 main1.txt 中读取出两个多项式,比如:

 然后会将结果写入D盘中的 main2.txt 文件中,即:

 而在编译器中运行这段代码会得到:

        这是正常的,另外我这段代码是在 Visual Studio 2017 中运行的。运行过程中你可能会碰到这样的错误:

解决办法的操作步骤如下:

1. 项目->属性

 2. 配置属性->C/C++->预处理器->预处理器定义->编辑

 3. 写入 _CRT_SECURE_NO_WARNINGS


欢迎指正我的上一篇博客:一元多项式的相乘操作(链表)

我的下一篇博客:对scansup.cpp的解析(一)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔走的月光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值