【C->数据结构与算法】->用线性表实现多项式求和->线性表工具库的应用

之前我们做了线性表的工具库,现在我们来利用这个工具库实现多项式的求和。

多项式求和:
例如 3.1564x^12 - 4.555687x^10 + …… = ……

这便是我们这个代码要解决的问题。

之前我们在userType.h头文件里定义了USER_TYPE类型,我们需要将int类型改变,以实现我们求和的功能。

多项式的每一项分成两个部分,系数和指数,像上面的例子,系数可以是个小数可以是个整数,可以有很多位,我们将其定义成double类型的,系数我们将其定义成整数类型。所以我们需要一个结构体。

以下为userType.h头文件里的代码:

#ifndef _USER_TYPE_H_
#define _USER_TYPE_H_

//用户在此可以更改需要的数据类型

typedef struct POLYNOMIAL {
	double coefficient;         //系数
	int exponent;               //指数
}POLY_ITEM, USER_TYPE;  

#endif

我们定义了一个结构体,用来定义多项式中的一项,为增加程序的可读性,我们将该类型同时定义为POLY_ITEM类型,代表一项多项式。

第一个要考虑的问题,仍然是初始化以及销毁。因为有工具库,所以我们很多函数不需要再去写。以下为初始化和销毁的函数:

boolean initPolynomial(POLYNOMIAL **head, int capacity) {
	initLinear(head, capacity);
}

void destoryPolynomial(POLYNOMIAL **head) {
	destoryLinear(head);
}

我们在polynomial.h的头文件中,同意为增加程序的可读性,将LINEAR类型同时定义为POLYNOMIAL类型。以下为polynomial.h中的代码:

#ifndef _TYZ_POLYNOMIAL_H_
#define _TYZ_POLYNOMIAL_H_

#include "linear.h"
#include "userType.h"
#include "tyz.h"

typedef LINEAR POLYNOMIAL;

boolean initPolynomial(POLYNOMIAL **head, int capacity);
void destoryPolynomial(POLYNOMIAL **head);

#endif

完成了基本的函数,我们接下来就要开始从最主要的地方入手。要得到两个多项式的和,我们首先需要录入。因此,我们先编写录入函数。
以下为录入函数的代码:

boolean enterPolynomial(POLYNOMIAL *head) {
	double coefficient;
	int exponent;
	int count = getCount(head);
	POLY_ITEM item;

	if (NULL == head) {
		return FALSE;
	}
	if (count > 0) {
		printf("录入功能只能对空多项式进行^_^\n");
		return FALSE;
	}

	printf("请按幂指数降序录入多项式^>^\n");
	printf("请输入系数和幂指数(当系数为0时,停止录入):\n");
	scanf("%lf %d",&coefficient,&exponent);

	while (fabs(coefficient) > 1e-6 && !isLinearFull(head)) {
		item.coefficient = coefficient;
		item.exponent = exponent;
		appendElement(head, item);

		printf("请输入系数和幂指数(当系数为0时,停止录入):\n");
		scanf("%lf %d",&coefficient,&exponent);
	}

	return TRUE;
}

用户的录入规则是:按幂指数降序录入,既符合我们一般写多项式的原则,也为我们之后的求和带来方便,我们约定,只要用户输入的系数不为零,就可以一直录入,直到线性表的空间满了为止,这也是为用户的考虑,让用户不用一开始就想要录入几个多项式,我们给他方便,只要他想停止录入,输入0即可。

录入完成,我们需要完成显示的函数。先将任务拆解,要显示整个多项式,我们先显示其中一项多项式,这样编写就简单的多了。

我们回到之前的那个多项式的例子
3.1564x^12 - 4.555687x^10 + …… = ……
我们想要输出的每一项由它的正负号、系数、x、^、指数构成。并且如果这一项是第一项且它的系数是正数,则不用输出它的正号。
所以我们加入了一个参数,isFirst,将其是否是第一项的判断加入进去,以决定是不是要输出‘+’。
另外要考虑的是,该项的指数为多少,如果指数是0,则不论x为多少其值都为1,故不用输出x,如果指数为1,则不用输出指数。
按这个方法考虑,就能输出符合人日常习惯的多项式了。

以下为显示一项多项式的函数:

void showPolyItem(POLY_ITEM item, boolean isFirst) {
	if (!isFirst && item.coefficient > 1e-6) {
		printf("+");
	}
	printf("%.2lf", item.coefficient);

	if (item.exponent != 0) {
		printf("x");
	}
	if (item.exponent != 0 && item.exponent != 1) {
		printf("^%d", item.exponent);
	}
}

输出一项的函数做完,输出整个多项式的函数就很简单了,只需要把输出单项的函数放入循环里就可以了。
以下为输出整个多项式的函数:

void showPolynomial(const POLYNOMIAL *head) {
	int index;
	int count = getCount(head);
	POLY_ITEM item;

	for (index = 0; index < count; index++) {
		getElement(head, index, &item);
		showPolyItem(item, i == 0);
	}
	printf("\n");
}

这里面用到的好几个函数都是之前工具库里的,所以十分方便,在用showPolyItem函数时,我们传递一个实参i == 0,当i != 0时,即不是第一个,该式子值为0,传递给形参isFirst为0,通过这样形参与实参的传递,实现判断该式子是否是第一个的要求。

接下来,就是将两个多项式相加了。
我们先回想以下我们是如何做多项式相加的。比如有两个式子
a = 3x^4 + 45x^3 + 22x^2
b = 6x^4 - 33x^3 - 18x
则 a + b = (3+6)x^4 + (45-33)x^3 + 22x^2 - 18x
= 9x^4 + 12x^3 + 22x^2 - 18x

这个过程其实和编写代码是一样的,编程即把我们的手工过程用机器指令实现。
我们先比较了两个式子的指数,如果指数相等,则将两个式子的系数相加,如果两个式子不相等,则先比较后面的,最后将没有同类项的式子放在最后。我这个只是个简单的例子,如果大家多写几遍,就会发现我们所做的合并同类项,也是按照一步一步的步骤做完的,这个步骤就是程序。
以下为相加的函数代码

POLYNOMIAL *addPolynomial(const POLYNOMIAL *polyOne, const POLYNOMIAL *polyAnother) {
	int polyOneIndex = 0;
	int polyAnotherIndex = 0;
	int polyOneCount = getCount(polyOne);
	int polyAnotherCount = getCount(polyAnother);
	double newCoefficient;
	POLY_ITEM polyOneItem;
	POLY_ITEM polyAnotherItem;
	POLYNOMIAL *result = NULL;

	initPolynomial(&result, getCapacity(polyOne) + getCapacity(polyAnother));

	getElement(polyOne, polyOneIndex, &polyOneItem);
	getElement(polyAnother, polyAnotherIndex, &polyAnotherItem);

	while (polyOneIndex < polyOneCount && polyAnotherIndex < polyAnotherCount) {
		if (polyOneItem.exponent > polyAnotherItem.exponent) {
			appendElement(result, polyOneItem);
			getElement(polyOne, ++polyOneIndex, &polyOneItem);
			continue;
		}
		if (polyOneItem.exponent < polyAnotherItem.exponent) {
			appendElement(result, polyAnotherItem);
			getElement(polyAnother, ++polyAnotherIndex, &polyAnotherItem);
			continue;
		}
		newCoefficient = polyOneItem.coefficient + polyAnotherItem.coefficient;

		if (fabs(newCoefficient) > 1e-6) {
			polyOneItem.coefficient = newCoefficient;
			appendElement(result, polyOneItem);
		}
		getElement(polyOne, polyOneIndex, &polyOneItem);
		getElement(polyAnother, polyAnotherIndex, &polyAnotherItem);
	}

	while (polyOneIndex < polyOneCount) {
		appendElement(result, polyOneItem);
		getElement(polyOne, ++polyOneIndex, &polyOneItem);
	}

	while (polyAnotherIndex < polyAnotherCount) {
		appendElement(result, polyAnotherItem);
		getElement(polyAnother, ++polyAnotherIndex, &polyAnotherItem);
	}

	return result;
}

这个函数的返回值类型为POLYNOMIAL *, 即我们将结果可以放在一个指向POLYNOMIAL类型的指针里。
按照我们的手工过程,我们先比较两个式子的指数,如果第一个大,就将第一个式子先放到结果里,小的那个之后再处理,第二个大亦然。如果都不是,那两个式子的指数一定是相等的,所以我们将其相加,生成一个newCoefficient,如果不为0,则把第一个式子的系数变为这个新系数,放进结果里。
第一轮循环完成,我们将同类项合并完成,并将两个式子中指数大的那个式子处理完成,还剩的就是两个多项式里第一次比较中较小系数的式子,因此我们再用两个循环,将剩下的式子放进结果里。

以上就是线性表的应用,工具库的创建对未来的很多程序构建都会有重大作用,就好像面向对象的语言如Python,Java等等,Python其实就是用C语言编写的,其用的很多封装的函数,也是像这样一样编写出来的。掌握工具库的创建,对理解编程会很有帮助。

完整代码如下:
polynomial.h

#ifndef _TYZ_POLYNOMIAL_H_
#define _TYZ_POLYNOMIAL_H_

#include "linear.h"
#include "userType.h"
#include "tyz.h"

typedef LINEAR POLYNOMIAL;

boolean initPolynomial(POLYNOMIAL **head, int capacity);
void destoryPolynomial(POLYNOMIAL **head);
boolean enterPolynomial(POLYNOMIAL *head);
void showPolyItem(POLY_ITEM item, boolean isFirst);
void showPolynomial(const POLYNOMIAL *head);
POLYNOMIAL *addPolynomial(const POLYNOMIAL *polyOne, const POLYNOMIAL *polyAnother);

#endif

polynomial.c

#include <stdio.h>
#include <malloc.h>
#include <math.h>

#include "polynomial.h"
#include "tyz.h"
#include "linear.h"


boolean initPolynomial(POLYNOMIAL **head, int capacity) {
	return initLinear(head, capacity);
}

void destoryPolynomial(POLYNOMIAL **head) {
	destoryLinear(head);
}

boolean enterPolynomial(POLYNOMIAL *head) {
	double coefficient;
	int exponent;
	int count = getCount(head);
	POLY_ITEM item;

	if (NULL == head) {
		return FALSE;
	}
	if (count > 0) {
		printf("录入功能只能对空多项式进行^_^\n");
		return FALSE;
	}

	printf("请按幂指数降序录入多项式^>^\n");
	printf("请输入系数和幂指数(当系数为0时,停止录入):\n");
	scanf("%lf %d",&coefficient,&exponent);

	while (fabs(coefficient) > 1e-6 && !isLinearFull(head)) {
		item.coefficient = coefficient;
		item.exponent = exponent;
		appendElement(head, item);

		printf("请输入系数和幂指数(当系数为0时,停止录入):\n");
		scanf("%lf %d",&coefficient,&exponent);
	}

	return TRUE;
}

void showPolyItem(POLY_ITEM item, boolean isFirst) {
	if (!isFirst && item.coefficient > 1e-6) {
		printf("+");
	}
	printf("%.2lf", item.coefficient);

	if (item.exponent != 0) {
		printf("x");
	}
	if (item.exponent != 0 && item.exponent != 1) {
		printf("^%d", item.exponent);
	}
}

void showPolynomial(const POLYNOMIAL *head) {
	int index;
	int count = getCount(head);
	POLY_ITEM item;

	for (index = 0; index < count; index++) {
		getElement(head, index, &item);
		showPolyItem(item, index == 0);
	}
	printf("\n");
}

POLYNOMIAL *addPolynomial(const POLYNOMIAL *polyOne, const POLYNOMIAL *polyAnother) {
	int polyOneIndex = 0;
	int polyAnotherIndex = 0;
	int polyOneCount = getCount(polyOne);
	int polyAnotherCount = getCount(polyAnother);
	double newCoefficient;
	POLY_ITEM polyOneItem;
	POLY_ITEM polyAnotherItem;
	POLYNOMIAL *result = NULL;

	initPolynomial(&result, getCapacity(polyOne) + getCapacity(polyAnother));

	getElement(polyOne, polyOneIndex, &polyOneItem);
	getElement(polyAnother, polyAnotherIndex, &polyAnotherItem);

	while (polyOneIndex < polyOneCount && polyAnotherIndex < polyAnotherCount) {
		if (polyOneItem.exponent > polyAnotherItem.exponent) {
			appendElement(result, polyOneItem);
			getElement(polyOne, ++polyOneIndex, &polyOneItem);
			continue;
		}
		if (polyOneItem.exponent < polyAnotherItem.exponent) {
			appendElement(result, polyAnotherItem);
			getElement(polyAnother, ++polyAnotherIndex, &polyAnotherItem);
			continue;
		}
		newCoefficient = polyOneItem.coefficient + polyAnotherItem.coefficient;

		if (fabs(newCoefficient) > 1e-6) {
			polyOneItem.coefficient = newCoefficient;
			appendElement(result, polyOneItem);
		}
		getElement(polyOne, polyOneIndex, &polyOneItem);
		getElement(polyAnother, polyAnotherIndex, &polyAnotherItem);
	}

	while (polyOneIndex < polyOneCount) {
		appendElement(result, polyOneItem);
		getElement(polyOne, ++polyOneIndex, &polyOneItem);
	}

	while (polyAnotherIndex < polyAnotherCount) {
		appendElement(result, polyAnotherItem);
		getElement(polyAnother, ++polyAnotherIndex, &polyAnotherItem);
	}

	return result;
}

linear.h

#ifndef _TYZ_LINEAR_H_
#define _TYZ_LINEAR_H_

#include "tyz.h"
#include "userType.h"

typedef struct LINEAR {
	USER_TYPE *data;
	int capacity;
	int count;
}LINEAR;

boolean initLinear(LINEAR **head, int capacity);
void destoryLinear(LINEAR **head);
int getCapacity(const LINEAR *head);
int getCount(const LINEAR *head);
boolean isLinearFull(const LINEAR *head);
boolean isLinearEmpty(const LINEAR *head);
boolean setElementAt(LINEAR *head, int index, USER_TYPE data);
boolean getElement(const LINEAR *head, int index, USER_TYPE *data);
boolean insertElementAt(LINEAR *head, int index, USER_TYPE data);
boolean appendElement(LINEAR *head, USER_TYPE data);
boolean removeElement(LINEAR *head, int index, USER_TYPE *data);
void clearLinear(LINEAR *head);

#endif

linear.c

#include <stdio.h>
#include <malloc.h>

#include "userType.h"
#include "tyz.h"
#include "linear.h"

boolean initLinear(LINEAR **head, int capacity) {
	if (NULL != *head) {
		return FALSE;
	}

	*head = (LINEAR *) calloc(sizeof(LINEAR),1);
	(*head)->capacity = capacity;
	(*head)->count = 0;
	(*head)->data = (USER_TYPE *) calloc(sizeof(USER_TYPE),capacity);

	return TRUE;
}

void destoryLinear(LINEAR **head) {
	if (NULL == head || NULL == *head) {
		return;
	}

	free((*head)->data);
	free(*head);

	*head = NULL;
}

int getCapacity(const LINEAR *head) {
	return head->capacity;
}

int getCount(const LINEAR *head) {
	return head->count;
}

boolean isLinearFull(const LINEAR *head) {
	return head->count >= head->capacity;
}

boolean isLinearEmpty(const LINEAR *head) {
	return head->count <= 0;
}

boolean setElementAt(LINEAR *head, int index, USER_TYPE data) {
	if (NULL == head || index < 0 || index >= head->count) {
		return FALSE;
	}

	head->data[index] = data;

	return TRUE;
}

boolean getElement(const LINEAR *head, int index, USER_TYPE *data) {
	if (NULL == head || index < 0 || index >= head->count) {
		return FALSE;
	}

	*data = head->data[index];

	return TRUE;
}

boolean insertElementAt(LINEAR *head, int index, USER_TYPE data) {
	int i;

	if (NULL == head || isLinearFull(head)
	     || index < 0 || index >= head->count) {
		return FALSE;
	}

	for (i = head->count; i > index; i--) {
		head->data[i] = head->data[i - 1];
	}
	head->data[index] = data;
	++head->count;

	return TRUE;
}

boolean appendElement(LINEAR *head, USER_TYPE data) {
	return insertElementAt(head, head->count, data);
}

boolean removeElement(LINEAR *head, int index, USER_TYPE *data) {
	if (NULL == head || isLinearEmpty(head)
		 || index < 0 || index >= head->count) {
		return FALSE;
	}
	*data = head->data[index];

	for (; index < head->count; index++) {
		head->data[index] = head->data[index + 1];
	}
	head->count--;

	return TRUE;
}

void clearLinear(LINEAR *head) {
	head->count = 0;
}

int getIndexOfElement(LINEAR *head, USER_TYPE data,
		boolean (*eq)(USER_TYPE,USER_TYPE)) {
	int index;
	int count = getCount(head);

	if (NULL == head || isLinearEmpty(head)) {
		return NOT_FOUND;
	}

	for (index = 0; index < count; index++) {
		if (eq(head->data[index],data)) {
			return index;
		}
	}

	return NOT_FOUND;
}

测试代码demo.c

#include <stdio.h>

#include "linear.h"
#include "polynomial.h"

int main(int argc, char const *argv[]) {
	POLYNOMIAL *polyOne = NULL;
	POLYNOMIAL *polyAnother = NULL;
	POLYNOMIAL *result = NULL;

	initPolynomial(&polyOne, 30);
	printf("以下录入第一个多项式:\n");
	enterPolynomial(polyOne);
	printf("以下为输入的第一个多项式:\n");
	showPolynomial(polyOne);

	initPolynomial(&polyAnother, 30);
	printf("以下录入第二个多项式:\n");
	enterPolynomial(polyAnother);
	printf("以下为输入的第二个多项式\n");
	showPolynomial(polyAnother);

	result = addPolynomial(polyOne, polyAnother);
	printf("以下为两个多项式之和:\n");
	showPolynomial(result);

	destoryPolynomial(&polyOne);
	destoryPolynomial(&polyAnother);
	destoryPolynomial(&result);

	return 0;
}


发布了10 篇原创文章 · 获赞 24 · 访问量 2459

猜你喜欢

转载自blog.csdn.net/qq_45627684/article/details/103367521
今日推荐