利用单链表进行多项式运算

1.这篇文章能给你带来什么?

        在本博客中,我将为大家介绍如何利用C++这一面向对象的编程语言实现单链表,并且将单链表应用于多项式加法和乘法之中。在本博文中,我将利用源代码为大家介绍以下内容:

       1.什么是运算符重载函数?

       2.什么是友元函数

       3.const函数的使用与作用

       4.单链表能为大家做些什么

2.正文

      总所周知数据结构由某一数据元素的集合和该集合中数据元素之间的关系组成,在数据存储上我们将物理内存单元连续的存储方式称之为线性结构,例如数组。物理内存单元不连续的称之为离散结构,数据之间的链接往往通过指针实现,例如链表,树结构和图结构。今天我们介绍的就是一种非线性结构--单链表,这种数据结构可以很好的解决多项式运算中,并且做到了内存空间上的节省。

                                                               y_{1}=1+2x^{2}+4x^{3}-3x^{4}

                                                               y_{2}=x-3x^{2}+4x^{4}-5x^{5}

       上面是两个多项式,我们可以用很多种数据结构来表示,比如说定义一个结构体数组,每一个数组的索引都和项的指数相等。如果多项式比较稀疏那么就会造成很大的内存空间浪费,这也是所有数组的通病。为此我们可以利用链表的结构极大地解决了空间浪费这一问题。

3.代码讲解

3.1  多项式节点结构体

struct Term {
	float coef;//系数									 
	int exp;   //指数
	Term *link;//指向下一个节点的指针
    /*构造函数*/
	Term(float c, int e, Term* next = NULL) {
		coef = c; exp = e; link = next;
	}
    /*结构体成员函数,尾插法插入链表,并返回新节点指针*/
	Term* InsertAfter(float c, int e);
    /*利用类的友元函数对多元运算符进行重载*/
	friend ostream& operator << (ostream&, const Term&);
};

 以上结构体为链表中每一个节点的数据结构,可以看出结构体与类的功能大同小异,结构体与类的区别请看以下链接:

链接:C++中结构体与类的区别

下面你可能会问以下两个问题:一、为什么要用到运算符重载?二、为什么会用到友元函数?下面我给大家一一说明。

在C++中<<是将输出流输出到控制台的运算符,我们可以cout<<(int,float,string....)等等数据类型的输出流,但是<<对于一个结构体对象或者类对象就会无能为力了。假设我们定义一个Term类型的对象T,如果没有声明关于<<的重载函数,编译器会报错:无法找到关于<<的重载函数。以下是关于C++中重载函数运算符重载我认为比较好的教程,大家可以看一看。

关于这里我们为什么将友元函数用在了operator函数重载上,我给大家讲一下。我们假设有一个类class,这个类有两个数据成员a和b,我们定义了两个对象a1和a2,如果没有运算符+的重载函数,我们无法直接进行a1+a2。这里我们可以定义一个operator+()函数使得a1+a2等价于a1.a+a2.a,a1.b+a2.b,这里a1+a2等价于a1.operator(a2),相当于将对象a2中的a和b这俩数据成员加到了对象a1的a和b中。在<<的重载函数中有两个形参,所以我们可以利用友元函数对运算符进行重载。这里有一个关于友元函数对运算符进行重载的小例子,大家可以看看。

3.2单链表数据结构

class Polynomial {
private:
	Term* first;
public:
	Polynomial() { first = new Term(0, -1); }			//默认构造函数
	Polynomial(Polynomial& R);							//复制构造函数
	friend Polynomial& operator+(Polynomial& L, Polynomial& R);//两个Polynomial类的对象相加得到一个新的Polynomial类的对象
	friend Polynomial& operator*(Polynomial& L, Polynomial& R);//对运算符*进行重载
	friend ostream& operator<<(ostream& out, Polynomial& L);//输出流运算符<<重载
	friend istream& operator >> (istream& in, Polynomial& L);//输入流运算符>>重载
	Term* GetHead()const { return first; }				//返回头结点指针
	int GetMaxExp();									//返回最大的指数的值
};

4.整体代码 

#pragma once
#include<iostream>
#include<algorithm>
using namespace std;
/*为何设计为struct,因为系数和指数都可以被直接被访问*/
struct Term {
	float coef;										 
	int exp;
	Term *link;
	Term(float c, int e, Term* next = NULL) {
		coef = c; exp = e; link = next;
	}
	Term* InsertAfter(float c, int e);
	friend ostream& operator << (ostream&, const Term&);//利用类的友元函数对多元运算符进行重载
};
class Polynomial {
private:
	Term* first;
public:
	Polynomial() { first = new Term(0, -1); }			//默认构造函数
	Polynomial(Polynomial& R);							//复制构造函数
	friend Polynomial& operator+(Polynomial& L, Polynomial& R);//两个Polynomial类的对象相加得到一个新的Polynomial类的对象
	friend Polynomial& operator*(Polynomial& L, Polynomial& R);//对运算符*进行重载
	friend ostream& operator<<(ostream& out, Polynomial& L);//输出流运算符<<重载
	friend istream& operator >> (istream& in, Polynomial& L);//输入流运算符>>重载
	Term* GetHead()const { return first; }				//返回头结点指针
	int GetMaxExp();									//返回最大的指数的值
};
Term * Term::InsertAfter(float c, int e) {
	link = new Term(c, e);
	return link;
}
ostream& operator<<(ostream& out, const Term& x) {
	if (x.coef == 0) { return out; }
	out << x.coef;
	switch (x.exp) {
		case 0:break;						//指数为0,只输出系数
		case 1:out << "X"; break;			//指数为1,只输出X与X的系数
		default:out << "X^" << x.exp; break;//默认
	}
	return out;
}
Polynomial::Polynomial(Polynomial& R) {
	first = new Term(0, -1);
	Term *dstptr = first; Term *srcptr = R.GetHead();
	while (srcptr != NULL) {
		dstptr->InsertAfter(srcptr->coef, srcptr->exp);
		dstptr = dstptr->link; srcptr = srcptr->link;
	}
}
/*零多项式返回-1,否则返回最后一项的指数*/
int Polynomial::GetMaxExp() {
	Term *Current = first;
	while (Current->link != NULL) {
		Current = Current->link;
	}
	return Current->exp;
}
/*      定义一个Polynomial类的友元函数operator+(),
        在该函数里面所有对象都可以访问Polynomial类的私有成员,
		注意这个函数不是Polynomial类里面的成员函数
*/
Polynomial& operator+(Polynomial& L, Polynomial& R){
	Term *LCurrent, *RCurrent, *NewCurrent,*p;//p是指向L和R较长的那一段剩下的链表
	float tempSum; Polynomial C;//自动调用默认构造函数,first->coef=0,first->exp=-1,link=NULL
	LCurrent = L.first->link; RCurrent = R.first->link; NewCurrent = C.first;//友元函数可以直接访问该类的私有成员first
	while (LCurrent != NULL && RCurrent != NULL) {
		if (LCurrent->exp == RCurrent->exp) {
			tempSum = LCurrent->coef + RCurrent->coef;
			if (fabs(tempSum) > 0.0001) {
				NewCurrent = NewCurrent->InsertAfter(tempSum, LCurrent->exp);
			}
			LCurrent = LCurrent->link;
			RCurrent = RCurrent->link;
		}
		else if (LCurrent->exp < RCurrent->exp) {
			NewCurrent = NewCurrent->InsertAfter(LCurrent->coef, LCurrent->exp);
			LCurrent = LCurrent->link;
		}
		else {
			NewCurrent = NewCurrent->InsertAfter(RCurrent->coef, RCurrent->exp);
			RCurrent = RCurrent->link;
		}
	}
	if (LCurrent != NULL) {
		p = LCurrent;
	}
	else{
		p = RCurrent;
	}
	while (p != NULL) {
		NewCurrent = NewCurrent->InsertAfter(p->coef, p->exp);
		p = p->link;
	}
	return C;
}
Polynomial& operator*(Polynomial& L, Polynomial& R) {
	Polynomial C; int ExpSum;
	Term *LCurrent, *RCurrent, *NewCurrent;
	NewCurrent = C.first;
	int maxExp = L.GetMaxExp() + R.GetMaxExp();
	float *result = new float[maxExp + 1];//指定指数对应的系数之和
	for (int i = 0; i <= maxExp; i++) { result[i] = 0.0; }
	LCurrent = L.first->link;  NewCurrent = C.first;
	while (LCurrent != NULL) {
		RCurrent = R.first->link;
		while (RCurrent != NULL) {
			ExpSum = LCurrent->exp + RCurrent->exp;//指数相加
			result[ExpSum] += LCurrent->coef * RCurrent->coef;//
			RCurrent = RCurrent->link;
		}
		LCurrent = LCurrent->link;
	}
	for (int i = 0; i <= maxExp; i++) {
		if (fabs(result[i]) > 0.001) {
			NewCurrent = NewCurrent->InsertAfter(result[i], i);
		}
	}
	delete[]result;
	return C;
}
ostream& operator<<(ostream& out, Polynomial& L) {
	Term* Current = L.first->link;
	bool first = true;//多项式第一个系数前面没有符号
	while (Current != NULL) {
		if (first == false && Current->coef > 0) {//添加+号
			out << "+";
		}
		first = false;
		out << *Current;//自动调用ostream&类型的<<重载函数operator<<(ostream&,Term&)
		Current = Current->link;
	}
	return out;
}
/*利用尾插法*/
istream& operator >> (istream& in, Polynomial& L) {
	Term* Current; int c, e;
	Current = L.first;
	while (1) {
		in >> c >> e;
		if (e < 0) { break; }
		Current = Current->InsertAfter(c, e);
	}
	return in;
}


以上代码是Polynomal.h的内容

#include<iostream>
#include"Polynomal.h"
using namespace std;
int main() {
	Polynomial P1,P2,Output1,Output2;
	cout << "请依次输入多项式P1的系数与指数!以指数为负为停止标志" << endl;
	cin >> P1;
	cout << "您输入的多项式为:" << endl;
	cout <<"Y="<< P1<<endl;
	cout << "请依次输入多项式P2的系数与指数!以指数为负为停止标志" << endl;
	cin >> P2;
	cout << "您输入的多项式为:" << endl;
	cout <<"Y="<< P2<<endl;
	Output2 = P1 * P2;
	cout << "得到的多项式为:" << endl;
	cout <<"Y="<< Output2 << endl;
	getchar();
	return 0;
}

以上为main.cpp的内容

5.运行结果

上图为多项式相乘的结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值