数据结构-数组--多项式表示(附完整代码)

多项式表示

  • 数组
    • 作为一种抽象数据类型
  • 多项式抽象数据类型
    • 有序表
    • 多项式的表示
      • 表示法1
      • 表示法2
      • 表示法3
    • 多项式的加法
      • 实现方法
      • 函数分析
    • 多项式乘法
  • 代码总览

数组

作为一种抽象数据类型

  • 抽象数据类型(ADT, Abstract Data Type)
    详细内容见: 数据结构-基本概念–数据
  • 对于数组 ,我们不能仅仅将其作为内存位置的连续位置;
  • 从直觉上看,数组是一个二元组 < i n d e x , v a l u e > <index,value>的集合,每个下标 i n d e x index index对应一个与其相关的值 v a l u e value value,数学上将其关联关系成为对应或映射
  • 数组的三种基本操作:产生新数组、获取(Retrieve)一个值、存储(Store)一个值。

多项式抽象数据类型

有序表

数组不仅本身是一种数据结构,也可以用来实现其他的抽象数据类型,其中包括最简单最常用的数据结构之一:有序表。例如以下例子:

  • 扑克牌花色的值(Ace、1、2…)
  • 一周的每一天(星期一、二…)

在有序表中要实现的操作:

  • 求有序表的长度;
  • 取出、删除表中第i个元素;
  • 在第i位置存储、插入一个新值;
    。。。。。。

多项式的表示

用有序表描述和操作一元多项式,例如:

  • a ( x ) = 3 x 2 + 2 x − 4 a(x)=3x^2+2x-4 a(x)=3x2+2x4
  • b ( x ) = x 8 − 10 x 5 − 3 x 3 + 1 b(x)=x^8-10x^5-3x^3+1 b(x)=x810x53x3+1

每个多项式都有阶数及其对应的系数,对于多项式的的。假设 a ( x ) = ∑ a i x i a(x)=\sum a_ix^i a(x)=aixi以及 b ( x ) = ∑ b i x i b(x)=\sum b_ix^i b(x)=bixi,那么,

  • a ( x ) + b ( x ) = ∑ ( a i + b i ) x i a(x)+b(x)=\sum (a_i+b_i)x^i a(x)+b(x)=(ai+bi)xi
  • a ( x ) × b ( x ) = ∑ ( a i x i × ∑ ( b j x j ) ) a(x)\times b(x)=\sum (a_ix^i \times\sum(b_jx^j)) a(x)×b(x)=(aixi×(bjxj))

对于 P ( x ) = a 0 x e 0 + . . . + a n x e n P(x)=a_0x^{e_0}+...+a_nx^{e_n} P(x)=a0xe0+...+anxen多项式ADT部分(成员函数)定义如下,包括加法、乘法等功能:

class Polynomial 
{
	//P(x)是的有序集合,
	//a_i(float)为阶数e_i(int)的系数;
public:
	Polynomial();
	//默认构造函数

	Polynomial Add(Polynomial temp);
	//返回多项式之和<*this+temp>

	Polynomial Mult(Polynomial temp);
	//返回多项式乘积<*this * temp>

	float Eval(float x);
	//计算*this多项式变量为x时的值

private:
	// 待确定
};

接下来要确定私有成员数据的表示方法,即如何表示一个多项式,下面将介绍三种表示方法。

表示法1

private:
	int degree;            //degree<=MaxDegree
	float coef[MaxDegree+1]  //系数数组
  • MaxDegree是一个 常量 ,代表该多项式类的最大阶数;
  • 如果a为一个类对象,a的最大阶数为 n , 且 n ≤ M a x D e g r e e n,且n\le MaxDegree n,nMaxDegree,则 a ( x ) a(x) a(x)可以表示为:
    a . d e g r e e = n a.degree = n a.degree=n
    a . c o e f [ i ] = a n − i , 0 ≤ i ≤ n a.coef[i] = a_{n-i},0\le i\le n a.coef[i]=ani,0in
  • 系数按照指数降序的顺序存储

表示法2

如果 a . d e g r e e a.degree a.degree M a x D e g r e e MaxDegree MaxDegree小很多,就会导致数组 a . c o e f [ ] a.coef[ ] a.coef[]大多数位置不会使用,导致内存浪费,可以通过定义变量 c o e f coef coef来实现,大小为 d e g r e e + 1 degree+1 degree+1,私有数据类型如下:

private:
	int degree;            //degree<=MaxDegree
	float *coef;           //系数数组

添加构造函数如下:

Polynomial::Polynomial(int d)
{
	degree = d;
	coef = new float[degree+1];
}

表示法3

表示法2解决了表示法1的问题,但对于一个多项式,它的很多系数为0,即 “稀疏多项式”。比如,多项式 x 1000 + 1 x^{1000}+1 x1000+1,只有两个非零系数,其余999个系数均为0。所以我们可以只存储非0项,定义一个 T e r m Term Term存储非零项。

  • 多项式类的完整定义如下:
class Polynomial;

class Term        //非零项
{
	friend Polynomial;
private:
	int exp;       //非零项指数
	float coef;    //该非零阶数的系数
};


class Polynomial 
{
private:
	Term* termArray;    //多项式非零项
	int terms;          //非零项数

public:
	Polynomial(int e[], float c[], int t);
	//构造函数1

	Polynomial(int t);
	//构造函数2

	Polynomial();
	//默认构造函数

	void NewTerm(const float theCoef, const int theExp);
	//termArray容量+1

	Polynomial Add(Polynomial temp);
	//返回多项式之和<*this+temp>

	Polynomial Mult(Polynomial temp);
	//返回多项式乘积<*this * temp>

	float Eval(float x);
	//计算*this多项式变量为x时的值

	const Polynomial& operator = (const Polynomial& temp);
	//等号重载,后续传参

	void P_Show();
	//打印结果
};

多项式的加法

实现方法

  • 表示法3存储多项式并进行加法操作,函数Add将 a ( x ) ( ∗ t h i s ) a(x)(*this) a(x)(this) b ( x ) b(x) b(x)相加产生 c ( x ) c(x) c(x)
  • 因为在 构造 c ( x ) c(x) c(x)调用的时默认构造函数(默认 t e r m s terms terms为0),所以在 逐项相加 时,要扩大 c ( x ) . t e r m A r r a y c(x).termArray c(x).termArray的容量,所以我们先实现容量拓展的操作,代码如下:
void Polynomial::NewTerm(const float theCoef, const int theExp)
{
	Term* temp = new Term[terms + 1];

	//将旧termArray拷贝到temp中
	copy(termArray, termArray + terms, temp);

	//释放旧termArray内存
	if(termArray!=NULL)	
		delete[]termArray;

	//新termArray指针指向temp
	termArray = temp;

	termArray[terms].exp = theExp;
	termArray[terms++].coef = theCoef;
}
  • 接下来进行加法操作,代码如下:
Polynomial Polynomial::Add(Polynomial temp)
{
	Polynomial result;
	int aPos = 0, bPos = 0;

	while (aPos < terms && bPos < temp.terms)
	{
		if (termArray[aPos].exp == temp.termArray[bPos].exp)
		{
			float f = termArray[aPos].coef + temp.termArray[bPos].coef;
			if (f)result.NewTerm(f, termArray[aPos].exp);
			aPos++;
			bPos++;
		}
		else if (termArray[aPos].exp < temp.termArray[bPos].exp)
		{
			result.NewTerm(temp.termArray[bPos].coef, temp.termArray[bPos].exp);
			bPos++;
		}
		else
		{
			result.NewTerm(termArray[aPos].coef, termArray[aPos].exp);
			aPos++;
		}
	}

	//循环结束没有完全遍历termArry情况
	for (; aPos < terms; aPos++)
		result.NewTerm(termArray[aPos].coef, termArray[aPos].exp);
	//循环结束没有完全遍历temp.termArray情况
	for (; bPos < temp.terms; bPos++)
		result.NewTerm(temp.termArray[bPos].coef, temp.termArray[bPos].exp);

	return result;
}

函数分析

  • 假设 a ( x ) a(x) a(x) b ( x ) b(x) b(x)中的非零项的数目为 m m m n n n,在 w h i l e while while每次循环中, a P o s 和 b P o s aPos和bPos aPosbPos或者分别增加1,或同时增加1。在 w h i l e while while循环结束时,不是 a P o s = = a . t e r m s aPos==a.terms aPos==a.terms,就是 b P o s = = b . t e r m s bPos==b.terms bPos==b.terms,没有完全遍历的在后面的 f o r for for循环中完全遍历
  • 分析可得最大重复次数为 m + n − 1 m+n-1 m+n1,所以整个过程所用时间为 O ( m + n + 扩 展 容 量 所 用 时 间 ) O(m+n+扩展容量所用时间) O(m+n+),而拓展容量的时间复杂度为 O ( 1 ) O(1) O(1),所以整个过程所用时间依然是 O ( m + n ) O(m+n) O(m+n)

多项式乘法

  • 表示法3存储多项式并进行乘法操作,函数Add将 a ( x ) ( ∗ t h i s ) a(x)(*this) a(x)(this) b ( x ) b(x) b(x)相乘产生 c ( x ) c(x) c(x)
  • a ( x ) ( ∗ t h i s ) a(x)(*this) a(x)(this)每一项与 b ( x ) b(x) b(x)相乘得到 t e r m s terms terms个多项式,再将 t e r m s terms terms个多项式相加即可得到结果。
    代码如下:
Polynomial Polynomial::Mult(Polynomial temp)
{
	Polynomial result;
	Polynomial temp_m(temp.terms);

	for (int i = 0; i < terms; i++)
	{
		for (int j = 0; j < temp.terms; j++)
		{
			temp_m.termArray[j].exp = termArray[i].exp + temp.termArray[j].exp;
			temp_m.termArray[j].coef = termArray[i].coef * temp.termArray[j].coef;
		}
		
		result = result.Add(temp_m);
	}

	return result;
}

代码总览

  • 可以自己定义,可以打印结果检查 ;
#include
using namespace std;

class Polynomial;

class Term        //非零项
{
	friend Polynomial;
private:
	int exp;       //非零项指数
	float coef;    //该非零阶数的系数
};


class Polynomial 
{
private:
	Term* termArray;    //多项式非零项
	int terms;          //非零项数

public:
	Polynomial(int e[], float c[], int t);
	//构造函数1

	Polynomial(int t);
	//构造函数2

	Polynomial();
	//默认构造函数

	void NewTerm(const float theCoef, const int theExp);
	//termArray容量+1

	Polynomial Add(Polynomial temp);
	//返回多项式之和<*this+temp>

	Polynomial Mult(Polynomial temp);
	//返回多项式乘积<*this * temp>

	float Eval(float x);
	//计算*this多项式变量为x时的值

	const Polynomial& operator = (const Polynomial& temp);
	//等号重载

	void P_Show();
	//打印结果
};

Polynomial::Polynomial(int e[], float c[], int t)
{
	terms = t;
	termArray = new Term[t];
	for (int i = 0; i < t; i++)
	{
		termArray[i].exp = e[i];
		termArray[i].coef = c[i];
	}
}

Polynomial::Polynomial(int t)
{
	terms = t;
	termArray = new Term[terms];
}

Polynomial::Polynomial()
{
	terms = 0;
	termArray = NULL;
}

void Polynomial::NewTerm(const float theCoef, const int theExp)
{
	Term* temp = new Term[terms + 1];

	//将旧termArray拷贝到temp中
	copy(termArray, termArray + terms, temp);

	//释放旧termArray内存
	if(termArray!=NULL)	
		delete[]termArray;

	//新termArray指针指向temp
	termArray = temp;

	termArray[terms].exp = theExp;
	termArray[terms++].coef = theCoef;
}

Polynomial Polynomial::Add(Polynomial temp)
{
	Polynomial result;
	int aPos = 0, bPos = 0;

	while (aPos < terms && bPos < temp.terms)
	{
		if (termArray[aPos].exp == temp.termArray[bPos].exp)
		{
			float f = termArray[aPos].coef + temp.termArray[bPos].coef;
			if (f)result.NewTerm(f, termArray[aPos].exp);
			aPos++;
			bPos++;
		}
		else if (termArray[aPos].exp < temp.termArray[bPos].exp)
		{
			result.NewTerm(temp.termArray[bPos].coef, temp.termArray[bPos].exp);
			bPos++;
		}
		else
		{
			result.NewTerm(termArray[aPos].coef, termArray[aPos].exp);
			aPos++;
		}
	}

	//循环结束没有完全遍历termArry情况
	for (; aPos < terms; aPos++)
		result.NewTerm(termArray[aPos].coef, termArray[aPos].exp);
	//循环结束没有完全遍历temp.termArray情况
	for (; bPos < temp.terms; bPos++)
		result.NewTerm(temp.termArray[bPos].coef, temp.termArray[bPos].exp);

	return result;
}

Polynomial Polynomial::Mult(Polynomial temp)
{
	Polynomial result;
	Polynomial temp_m(temp.terms);

	for (int i = 0; i < terms; i++)
	{
		for (int j = 0; j < temp.terms; j++)
		{
			temp_m.termArray[j].exp = termArray[i].exp + temp.termArray[j].exp;
			temp_m.termArray[j].coef = termArray[i].coef * temp.termArray[j].coef;
		}
		result = result.Add(temp_m);
	}

	return result;
}

float Polynomial::Eval(float x)
{
	P_Show();
	cout << "x=" << x << "时,P(x)=";
	float result = 0;

	for (int i = 0; i < terms; i++)
	{
		float n = 1;
		for (int j = 0; j < termArray[i].exp; j++)
		{
			n *= x;
		}
		n *= termArray[i].coef;
		result += n;
	}

	return result;
}

const Polynomial& Polynomial:: operator = (const Polynomial& temp)
{
	terms = temp.terms;
	if (termArray != NULL)
		delete[]termArray;

	termArray = new Term[terms];
	copy(temp.termArray, temp.termArray + terms, termArray);

	return *this;
}

void Polynomial::P_Show()
{
	cout << "多项式为:P(x)=" ;
	if (terms > 0)
	{
		int i = 0;
		while (i < terms)
		{
			if (termArray[i].coef > 0)cout << "+" << termArray[i].coef;		
			else cout << termArray[i].coef;

			if (termArray[i].exp != 0)cout << "x^" << termArray[i].exp<<"\t";
				i++;
		}
	}
	else cout << 0;
	
	cout << ",\t项数为:"<<terms <<endl<< endl;
}


int main()
{
	int e1[5] = { 20,15,12,8,0 }, e2[4] = { 30,20,15,8 };
	float c1[5] = { 4,-1,5,6,9 }, c2[4] = { 2,1,-7,6 };

	Polynomial a(e1, c1, 5), b(e2, c2, 4),c;

	a.P_Show();
	b.P_Show();

	c = a.Add(b);
	c.P_Show();

	c = a.Mult(b);
	c.P_Show();

	cout << a.Eval(2.5);
	
	return 0
}

你可能感兴趣的:(数据结构,数据结构,算法)