数据结构(二)—— 线性结构(4):应用实例

数据结构系列内容的学习目录 → \rightarrow 浙大版数据结构学习系列内容汇总

4. 应用实例

4.1 多项式加法运算

  例: 将多项式 P 1 = 3 x 5 + 4 x 4 − x 3 + 2 x − 1 P_{1}=3x^{5}+4x^{4}-x^{3}+2x-1 P1=3x5+4x4x3+2x1 P 2 = 2 x 4 + x 3 − 7 x 2 + 3 x − 1 P_{2}=2x^{4}+x^{3}-7x^{2}+3x-1 P2=2x4+x37x2+3x1进行相加。

在这里插入图片描述
  主要思路: 相同指数的项系数相加,其余部分进行拷贝。

  采用不带头结点的单向链表,按照指数递减的顺序排列各项。

在这里插入图片描述

struct PolyNode {
    int coef;  //系数
    int expon;  //指数
    struct PolyNode *link;  //指向下一个节点的指针
};
typedef struct PolyNode *Polynomial;
Polynomial P1,P2;

  算法思路: 两个指针P1和P2分别指向这两个多项式第一个结点,不断循环:
         ⋄ \diamond P1->expon==P2>expon:系数相加,若结果不为0,则作为结果多项式对应项的系数。同时,P1和P2都分别指向下一项;
         ⋄ \diamond P1->expon>P2->expon:将P1的当前项存入结果多项式,并使P1指向下一项;
         ⋄ \diamond P1->expon<P2->expon:将P2的当前项存入结果多项式,并使P2指向下一项。

  当某一多项式处理完时,将另一个多项式的所有结点依次复制到结果多项式中去。

在这里插入图片描述

Polynomial PolyAdd(Polynomial P1,Polynomial P2)
{
    Polynomial front, rear, temp;  //为方便表头插入,先产生一个临时空结点作为结果多项式链表头
    int sum;
    rear = (Polynomial) malloc(sizeof(struct PolyNode)); 
    front = rear;  //由front记录结果多项式链表头结点
    while (P1 && P2)  //当两个多项式都有非零项待处理时
    {
        switch (Compare(P1->expon, P2->expon))
		{
		case 1:  //P1中的数据项指数较大
			Attach(P1->coef, P1->expon, &rear);
			P1 = P1->link;
			break;
		case -1:  //P2中的数据项指数较大
			Attach(P2->coef, P2->expon, &rear);
			P2 = P2->link;
			break;
		case 0:  //两数据项指数相等
			sum = P1->coef + P2->coef;
			if (sum)  //注意判断系数和是否为0
				Attach(sum, P1->expon, &rear);
			P1 = P1->link;
			P2 = P2->link;
			break;
		}
    }
    //将未处理完的另一个多项式的所有节点依次复制到结果多项式中去
    for(; P1; P1=P1->link)  //P1不为空
        Attach(P1->coef,P1->expon, &rear);
    for(; P2; P2= P2->link )    //P2不为空
        Attach(P2->coef,P2->expon, &rear);
    rear->link = NULL;
    temp= front;
    front= front->link;  //令front指向结果多项式第一个非零项
    free(temp);  //释放临时空表头结点
    return front;
}

  新增一个结点的实现。

在这里插入图片描述

// 新增一个节点
void Attach(int c, int e, Polynomial*pRear)  //由于在本函数中需要改变当前结果表达式尾项指针的值,所以函数传递进来的是结点指针的地址,*pRear指向尾项
{
    Polynomial P;
    P=(Polynomial)malloc(sizeof(struct PolyNode));  //申请新结点
    P->coef = c;  //对新结点赋值
    P->expon = e;
    P->link=NULL;  //将P指向的新结点插入到当前结果表达式尾项的后面
    (*pRear)->link = P;
    *pRear = P;  //修改pRear值
}

  多项式加法运算的完整实现代码如下所示。

#include<iostream>
using namespace std;

struct PolyNode {
	int coef;  //系数
	int expon;  //指数
	struct PolyNode *link;  //指向下一个节点的指针
};
typedef struct PolyNode *Polynomial;
Polynomial P1, P2;

Polynomial PolyAdd(Polynomial P1, Polynomial P2);
void Attach(int c, int e, Polynomial *pRear);
int Compare(int a, int b);
void PrintPoly(Polynomial P);

Polynomial PolyAdd(Polynomial P1, Polynomial P2)
{
	Polynomial front, rear, temp;
	int sum;
	rear = (Polynomial)malloc(sizeof(struct PolyNode));  //为方便表头插入,先产生一个临时空结点作为结果多项式链表头
	front = rear;  //由front记录结果多项式链表头结点
	while (P1 && P2)  //当两个多项式都有非零项待处理时
	{
		switch (Compare(P1->expon, P2->expon))
		{
		case 1:  //P1中的数据项指数较大
			Attach(P1->coef, P1->expon, &rear);
			P1 = P1->link;
			break;
		case -1:  //P2中的数据项指数较大
			Attach(P2->coef, P2->expon, &rear);
			P2 = P2->link;
			break;
		case 0:  //两数据项指数相等
			sum = P1->coef + P2->coef;
			if (sum)  //注意判断系数和是否为0
				Attach(sum, P1->expon, &rear);
			P1 = P1->link;
			P2 = P2->link;
			break;
		}
	}
	//将未处理完的另一个多项式的所有节点依次复制到结果多项式中去
	for (; P1; P1 = P1->link)  //P1不为空
		Attach(P1->coef, P1->expon, &rear);
	for (; P2; P2 = P2->link)  //P2不为空
		Attach(P2->coef, P2->expon, &rear);
	rear->link = NULL;
	temp = front;
	front = front->link;  //令front指向结果多项式第一个非零项
	free(temp);  //释放临时空表头结点
	return front;
}

int Compare(int a, int b) 
{
	if (a > b)
		return 1;
	else if (a < b) 
		return -1;
	else 
		return 0;
}

// 新增一个节点
void Attach(int c, int e, Polynomial *pRear)  //由于在本函数中需要改变当前结果表达式尾项指针的值,所以函数传递进来的是结点指针的地址,*pRear指向尾项
{
	Polynomial P;
	P = (Polynomial)malloc(sizeof(struct PolyNode));  //申请新结点
	P->coef = c;  //对新结点赋值
	P->expon = e;
	P->link = NULL;  
	//将P指向的新结点插入到当前结果表达式尾项的后面
	(*pRear)->link = P;  // 尾节点指向P
	*pRear = P;  //修改pRear指针指向的值
}

void PrintPoly(Polynomial P)
{
	Polynomial tmp = P;
	for (; tmp; tmp = tmp->link)
	{ 
		cout << tmp->coef << "  " << tmp->expon << "    ";
	}
	cout << endl;
}

int main()
{
	int P1Coef[5] = { 3, 4, -1, 2, -1 };
	int P1expon[5] = { 5, 4, 3, 1, 0 };
	int P2Coef[4] = { 2, 1, -7, 1 };
	int P2expon[4] = { 4, 3, 2, 1 };

	P1 = (Polynomial)malloc(sizeof(struct PolyNode));
	P2 = (Polynomial)malloc(sizeof(struct PolyNode));

	Polynomial P1Rear;
	P1Rear = P1;

	Polynomial P2Rear;
	P2Rear = P2;

	for (int i = 0; i < 5; ++i)
	{
		Attach(P1Coef[i], P1expon[i], &P1Rear); // 注意这里传的是地址!!!
	}
	P1 = P1->link; // 因为第一个节点没有存储数据,所以 P1 要往后挪一位

	for (int i = 0; i < 4; ++i)
	{
		Attach(P2Coef[i], P2expon[i], &P2Rear);
	}
	P2 = P2->link;

	Polynomial res = PolyAdd(P1, P2);

	cout << "P1:   ";
	PrintPoly(P1);
	cout << "P2:   ";
	PrintPoly(P2);
	cout << "P1+P2:";
	PrintPoly(res);

	system("pause");

	return 0;
}

  代码运行结果如下图所示。

在这里插入图片描述

4.2 一元多项式的加法与乘法运算

  题意理解: 设计函数分别求两个一元多项式的乘积与和。
        已知两个多项式: P 1 = 3 x 4 − 5 x 2 + 6 x − 2 P_{1}=3x^{4}-5x^{2}+6x-2 P1=3x45x2+6x2 P 2 = 5 x 20 − 7 x 4 + 3 x P_{2}=5x^{20}-7x^{4}+3x P2=5x207x4+3x

        P 1 + P 2 = 5 x 20 − 4 x 4 − 5 x 2 + 9 x − 2 P_{1}+P_{2}=5x^{20}-4x^{4}-5x^{2}+9x-2 P1+P2=5x204x45x2+9x2
        多项式的乘积: ( a + b ) ( c + d ) = a c + a d + b c + b d (a+b)(c+d)=ac+ad+bc+bd (a+b)(c+d)=ac+ad+bc+bd
        P 1 ⋅ P 2 = 15 x 24 − 25 x 22 + 30 x 21 − 10 x 20 − 21 x 8 + 35 x 6 − 33 x 5 + 14 x 4 − 15 x 3 + 18 x 2 − 6 x P_{1}\cdot P_{2}=15x^{24}-25x^{22}+30x^{21}-10x^{20}-21x^{8}+35x^{6}-33x^{5}+14x^{4}-15x^{3}+18x^{2}-6x P1P2=15x2425x22+30x2110x2021x8+35x633x5+14x415x3+18x26x

  多项式的表示: 仅表示非零项。
          数组:1. 编程简单、调试容易;
             2. 需要事先确定数组大小。
          链表:1. 动态性强;
             2. 编程略为复杂、调试比较困难。
          一种比较好的实现方法是:动态数组。

  使用链表表示的数据结构设计如下所示。

typedef struct PolyNode *Polynomial;
struct PolyNode {
    int coef;
    int expon;
    Polynomial link;
};

在这里插入图片描述
  程序框架搭建:

int main()
{
    读入多项式1
    读入多项式2
    乘法运算并输出
    加法运算并输出
    
    return 0;
}

  需要设计的函数: 1. 读入多项式
           2. 两多项式相乘
           3. 两多项式相加
           4. 多项式输出

  一元多项式的加法与乘法运算的完整实现代码如下所示。

#include<iostream> 
using namespace std;

typedef struct PolyNode {
	int coef;//系数 
	int exp;//指数 
	struct PolyNode *next;
} *Polynomial;

Polynomial read(Polynomial P);
void print(Polynomial P);
Polynomial getMuti(Polynomial P1, Polynomial P2);
Polynomial getAdd(Polynomial P1, Polynomial P2);

Polynomial read(Polynomial P) 
{
	Polynomial s = NULL, temp;
	P = (struct PolyNode*)malloc(sizeof(struct PolyNode));
	temp = P;
	int n, COEF, EXP;
	cout << "多项式的项数:";
	cin >> n;
	cout << "多项式每项对应的系数和指数:";
	for (int i = 0; i < n; i++) 
	{
		cin >> COEF >> EXP;
		if (COEF != 0) 
		{
			s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
			s->coef = COEF; 
			s->exp = EXP;
			P->next = s;
			P = s;
		}
	}
	P->next = NULL;
	return temp;
}


void print(Polynomial P) 
{
	int num = 0, temp = 0;  //temp用于统计P里面有多少个元素,num 用于统计有多少个系数为0的数 
	Polynomial val = P;
	while (val->next) 
	{
		val = val->next;
		temp++;
	}
	if (P->next != NULL) 
	{
		while (P->next) 
		{
			if (P->next->coef != 0) 
			{
				cout << P->next->coef << " " << P->next->exp;
				Polynomial val = P->next;
				while (val->next&&val->next->coef == 0) 
				{
					val = val->next;
				}
				if (val->next == NULL)
					cout << endl;
				else
					cout << " ";
			}
			else
				num++;
			P = P->next;
		}
		if (num == temp)
			cout << 0 << " " << 0 << endl;
	}
	else
		cout << 0 << " " << 0 << endl;
}


Polynomial getAdd(Polynomial P1, Polynomial P2) 
{
	Polynomial P, temp = NULL, s = NULL;
	P = (struct PolyNode *)malloc(sizeof(struct PolyNode));
	temp = P;

	while (P1->next&&P2->next) 
	{
		if (P1->next->exp > P2->next->exp) 
		{
			s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
			s->coef = P1->next->coef;
			s->exp = P1->next->exp;
			P->next = s;
			P = s;
			P1 = P1->next;
		}
		else if (P1->next->exp < P2->next->exp) 
		{
			s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
			s->coef = P2->next->coef;
			s->exp = P2->next->exp;
			P->next = s;
			P = s;
			P2 = P2->next;
		}
		else 
		{
			s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
			s->coef = P2->next->coef + P1->next->coef;
			s->exp = P2->next->exp;
			P->next = s;
			P = s;
			P1 = P1->next;
			P2 = P2->next;
		}
	}
	if (P1->next)
		P->next = P1->next;
	else
		P->next = P2->next;
	return temp;
}


Polynomial getMuti(Polynomial P1, Polynomial P2) {
	/*
	在这里我们采用的是:逐项插入。
	1,先拿出P2的第一项,让它与P1的每一项相乘,从而得到P
	2,再拿出P2的第二项,让它与P1的每一项相乘,然后每乘一项,就将其插入到P中
	3,依次重复上面的步骤,最终得到P,将其打印出来
	*/
	Polynomial P, temp = NULL, s = NULL;
	P = (struct PolyNode *)malloc(sizeof(struct PolyNode));
	temp = P;
	Polynomial Pa = P1;

	//拿出P2的第一项,让它与P1的每一项相乘,从而得到P
	while (Pa->next) {
		s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
		s->coef = Pa->next->coef * P2->next->coef;  //P1的每一项与P2的第一项的系数相乘
		s->exp = Pa->next->exp + P2->next->exp;  //P1的每一项与P2的第一项的指数相加
		P->next = s;
		P = s;
		Pa = Pa->next;
	}
	P->next = NULL;
	P = temp;
	Polynomial Pb = P2->next;
	while (Pb&&Pb->next) 
	{
		Pa = P1;
		while (Pa->next) 
		{
			s = (struct PolyNode *)malloc(sizeof(struct PolyNode));
			s->coef = Pa->next->coef * Pb->next->coef;
			s->exp = Pa->next->exp + Pb->next->exp;
			while (P->next) 
			{
				if (s->exp > P->next->exp) 
				{
					Polynomial val = P->next;
					P->next = s;
					s->next = val;
					break;
				}
				else if (s->exp == P->next->exp)
				{
					P->next->coef += s->coef;
					break;
				}
				P = P->next;
			}
			if (P->next == NULL) 
			{
				P->next = s;
				s->next = NULL;
			}
			P = temp;
			Pa = Pa->next;
		}
		Pb = Pb->next;
	}
	return temp;
}

int main() 
{
	Polynomial P1 = NULL;
	Polynomial P2 = NULL;
	Polynomial P = NULL;
	cout << "P1:" << endl;
	P1 = read(P1);
	cout << "P2:" << endl;
	P2 = read(P2);

	cout << "P1*P2:";
	P = getMuti(P1, P2);
	print(P);

	cout << "P1+P2:";
	P = getAdd(P1, P2);
	print(P);

	system("pause");
	return 0;
}

  代码运行结果如下图所示。

在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值