【数据结构(10)】2.8 线性表的案例分析与实现

1. 一元多项式的运算

  • 实现两个多项式加、减、乘运算。

在这里插入图片描述

  • 将两个多项式存在数组里面,数组的下标就是每个系数的 x 的对应指数。

在这里插入图片描述

  • 排完之后多项式相加就很简单了,相同下标的都是系数相同的,直接相加就行了。
    • 用一个新的数组来存放相加之后的结果。

在这里插入图片描述

2. 稀疏多项式的运算

  • 只将系数不为0的每一项的系数和指数存储起来。
  • 线性表 P = ((p1,e1),(p2,e2),…(pm,em))

在这里插入图片描述

  • 把由系数和指数构成的序列就看成是一个线性表。

求这两个多项式的和:

线性表A = ((7,0),(3,1),(9,8),(5,17))
线性表B = ((8,1),(22,7),(-9,8))

  • 创建一个新数组 C
  • 分别从头遍历比较 a 和 b 的每一项。
    • 指数相同,对应系数相加,若其和不为0,则在c中增加一个新项。
    • 指数不相同,则将指数交小的项复制到c中。
  • 一个多项式已经遍历完毕时,将另一个剩余项依次复制到C中即可

稀疏多项式求和步骤

在这里插入图片描述

  1. 先把 A、B 两个数组的第一个元素的指数比较,A里面存的指数是0,比较小,先把 A 的第一个元素(7,0)存到C数组中,A 的第一项去掉不再参与计算。

在这里插入图片描述

  1. 将 A 的第二项(3,1)和 B 的第一项(8,1)的指数比较,指数都为1,则系数相加存入C,指数不变存入C,这两项去掉。

在这里插入图片描述

  1. 再将A的(9,8)和B的(22,7)比较,B 的指数比较小,将(22,7)存入 C 数组,然后去掉不再参与计算。

在这里插入图片描述

  1. 将 A 的(9,8)和 B 的(-9,8)比较,指数相同,则系数相加,系数相加为0,则这两项都删掉且不存入C数组。

在这里插入图片描述

  1. 多项式 B 已经遍历完成,则将 A 的剩余项复制到 C 即可。

在这里插入图片描述

数组C应该多大?

  • 最多,线性表A和B的每一项的指数都不同,那么数组C就要7项。
  • 最少,A和B每一项的指数都相同,且系数为相反数,那么结果就刚好是 0 项
  • 给C的空间如果多了有可能浪费,少了就有可能放不下,这个时候就需要用到链式存储结构了。

顺序存储结构存在的问题

  • 存储空间分配不灵活
  • 运算的空间复杂度高

链式存储结构

  • 不用数组来存储 A 和 B 的数据元素,不占用一块连续的空间,用链表的方式来存储,运算的时候需要多少就用多少空间。

在这里插入图片描述

结点定义

typedef struct PNode
{
	float coef;//系数
	int expn;//指数
	struct PNode* next;//指针域
}PNode,*pplynomial;
  • 一个多项式可以表示成由这些结点链接起来的单链表,要实现多项式的相加运算,优先需要创建多项式链表。

多项式创建

算法步骤

  1. 创建一个只有头结点的空链表。
  2. 根据多项式的项的个数 n,循环 n 次执行以下操作:
    • 生成一个新结点 *s;
    • 输入多项式当前项的系数和指数赋给新结点 *s 的数据域;
    • 设置一个前趋指针 pre,用于指向待找到的第一个大于输入项指数的结点的前趋,pre 初始值指向头结点;
    • 指针 p 初始化,指向首元结点;
    • 循链向下逐个比较链表中当前结点与输入项指数,找到第一个大于输入项指数的结点 *q;
    • 将输入项结点 *s 插入到结点 *q之前。

算法描述

//输入n项的系数和指数,建立表示多项式的有序链表p
void Createpolyn(polynoimal &P,int n)
{
	p = new PNode;
	p -> next = NULL;//先建立一个带头结点的单链表
	
	for(i = 1;i <= n;i++)//依次输入n各非零项
	{
		s = new PNode;//生成新结点
		cin >> s -> coef >> s -> expn;//输入系数和指数
		pre = p;//pre用于保存p的前趋,初始值为头结点
		q = p -> next;//q初始化,指向首元结点
	
		//找到第一个大于输入项指针的项*q
		while(q && q -> expn < s -> expn)
		{
			pre = q;
			q = q -> next;
		}
	
		s -> next = q;//将输入项s插入到q和其前趋结点pre之间
		pre -> next = s;
	}
}

多项式的相加

在这里插入图片描述

  • 比较两个链表的第一个结点,指数比较小的那个就作为新链表当中的元素,比较方法和用顺序表的没差别,两个结点的系数相加若是 0 则不管直接去看先一结点。

在这里插入图片描述

算法步骤

  1. 指针 p1 和 p2 初始化,分别指向 pa 和 pb 的首元结点。

  2. p3 指向和多项式的当前结点,初值为 pa 的头结点。

  3. 当指针 p1 和 p2 均为到达相应表尾时,则循环比较 p1 和 p2 所指向结点对应的指数值(p1 -> expnp2 -> expn),有下列三中情况:

    • p1 -> expn == p2 -> expn 时,则将两个结点中的系数相加:
      • 和不为零, 则修改 p1 所指向结点的系数值,同时删除 p2 所指向结点;
      • 和为零,则删除 p1 和 p2 所指向的结点;
    • p1 -> expn < p2 -> expn 时,则应摘取 p1 所指向结点插入到“和多项式”链表中去;
    • p1 -> expn > p2 -> expn 时,则应摘取 p2 所指向结点插入到“和多项式”链表中去。
  4. 将非空多项式的剩余段插入到 p3 所指向结点之后。

  5. 释放 pb 的头结点。

算法描述

//多项式加法:pa = pa+pb,利用两个多项式的结点构成“和多项式”
void Addpolyn(Polynomial &pa,polynomial &pb)
{
	p1 = pa -> next;p2 = pb -> next;//p1和p2初始值分别指向pa和pb的首元结点
	p3 = pa;//p3指向和多项式的当前结点,初始值为pa

	while(p1 && p2)///p1和p2均非空
	{
		if(p1 -> expn == p2 -> expn)//指数相等
		{
			sum = p1 -> coef + p2 -> coef;//保存两项的系数和
			if(sum)//系数和不为0
			{
				p1 -> coef = sum;//修改pa当前结点的系数值为两项系数的和
				p3 -> next = p1;p3 = p1;//将修改后的pa当前结点链接在p3之后,让p3指向p1
				p1 = pe -> next;//p1往后移动一位
				r = p2;p2 = pe -> next;delete r;//删除pb当前结点,让p2往后移一位
			}
			else//系数和为0
			{
				r = p1;p1 = p1 -> next;delete r;//删除pa当前结点,p1指向后一项
				r = p2;p2 = p2 -> next;delete r;//删除pb当前结点,p2指向后一项
			}
		}
		else if(p1 -> expn < p2 -> expn)//pa当前结点的指数值小
		{
			p3 -> next = p1;//将p1链在p3之后
			p3 = p1;//p3指向p1
			p1 = p1 -> next;//p1指向后一项
		}
		else//pb当前结点的指数值小
		{
			p3 -> next = p2;//将p2连接在p3之后
			p3 = p2;//让p3指向p2
			p2 = p2 -> next;//让p2指向后一项
		}
	}
	p3 -> next = p1?p1:p2;//插入非空多项式的剩余结点
	delete pb;//释放pb的头结点
}

3. 图书信息管理系统

  • 需要的功能:查找 、插入 、 删除 、修改 、排序 、计数

在这里插入图片描述

  • 图书表可以抽象为线性表(顺序表或链表)。
  • 表中每本图书抽象为线性表中的数据元素。

这个线性表可以用顺序表来实现,也可以用链表来实现。

  • 如果表中的图书数目变化不大,很少做删除(插入)操作,那么就用顺序存储方式;
  • 如果表中的图书数目变化大,经常要进行删除和插入操作,那么就用链式存储结构。

在这里插入图片描述

两种存储结构的结点类型定义

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值