数据结构-线性表的应用

目录

  • 前言
  • 一、有序表的合并
    • 1.1 顺序表实现
    • 1.2 单链表实现
  • 二、稀疏多项式的相加和相乘
    • 2.1 稀疏多项式的相加
    • 2.2 稀疏多项式的相乘
  • 总结

前言

本篇文章介绍线性表的应用,分别使用顺序表和单链表实现有序表的合并,最后介绍如何使用单链表实现两个稀疏多项式的相加和相乘。

一、有序表的合并

已知线性表La和Lb的数据元素按值非递减有序排列,现要求将La和Lb合并为一个新的线性表Lc,且Lc中的数据元素仍按值非递减有序排序。
非递减指可以有相同的值出现在同一个线性表中
L a = ( a , b , c ) La=(a,b,c) La=(a,b,c)
L b = ( c , d , e , f ) Lb=(c,d,e,f) Lb=(c,d,e,f)
L a La La L b Lb Lb合并后
L c = ( a , b , c , c , d , e , f ) Lc=(a,b,c,c,d,e,f) Lc=(a,b,c,c,d,e,f)

1.1 顺序表实现

算法步骤

  1. 创建一个空表Lc
  2. 依次从La或Lb中摘取元素值较小的结点插入到Lc表后,直至其中一个表变为空为止
  3. 继续将La或Lb其中一个表的剩余结点插图到Lc表的最后

代码实现如下

//定义返回值状态码
#define SUCCESS 1
#define ERROR   0//这里假设元素的数据类型为char
typedef char ElemType;//定义一个线性表
struct SeqList {int MAXNUM;			//线性表中最大元素的个数int n;				//线性表中实际的元素个数,n <= MAXNUMElemType* element;	//存放线性表元素,element[0],element[1]...element[n-1]
};//定义一个SeqList的指针类型
typedef struct SeqList* PSeqList;
//合并两个有序表
void mergeList_seq(PSeqList La, PSeqList Lb, PSeqList Lc)
{ElemType* pa = La->element;ElemType* pb = Lb->element;  //指针pa和pb分别指向两个表的第一个元素Lc->n = La->n + Lb->n;Lc->MAXNUM = Lc->n;Lc->element = (ElemType*)malloc(sizeof(Lc->n)); //为合并的新表分配一个数组空间if (NULL == Lc->element){printf("malloc fail!\n");exit(ERROR);}ElemType* pc = Lc->element;   //指针pc指向Lc表的第一个元素ElemType* pa_last = La->element + (La->n - 1); //指针pa_last指向La表的最后一个元素ElemType* pb_last = Lb->element + (Lb->n - 1); //指针pb_last指向Lb表的最后一个元素while (pa <= pa_last && pb <= pb_last){if (*pa <= *pb)*pc++ = *pa++;else*pc++ = *pb++;}while (pa <= pa_last) *pc++ = *pa++; //Lb表到达表尾,将La表中剩余元素加入Lcwhile (pb <= pb_last) *pc++ = *pb++; //La表到达表尾,将Lb表中剩余元素加入Lc
}

1.2 单链表实现

为了方便使用,选择带头结点的单链表

算法步骤

  1. pa和pb指针分别指向La和Lb的首元结点
  2. pc指向La的头结点,用La的头结点作为Lc的头结点
  3. 依次从La或Lb中摘取元素值较小的结点插入到Lc表后,直至其中一个表变为空为止
  4. 继续将La或Lb其中一个表的剩余结点插图到Lc表的最后

代码实现如下

//假设数据元素类型为char
typedef char ElemType;//定义结点类型
struct Node;				  	
typedef struct Node* PNode;   //假设作为结点指针类型
struct Node {ElemType data;   //数据域PNode next;		//指针域
};typedef struct Node* LinkList;  //假设作为单链表类型//合并两个有序表
//带头结点
void mergeList_link(LinkList* La, LinkList* Lb, LinkList* Lc)
{PNode pa = (*La)->next;PNode pb = (*Lb)->next;PNode pc = *La;*Lc = *La;      //用La的头结点作为Lc的头结点while (pa && pb){if (pa->data <= pb->data){pc->next = pa;pc = pa;pa = pa->next;}else{pc->next = pb;pc = pb;pb = pb->next;}}pc->next = pa ? pa : pb;  //插入剩余元素free(*Lb);				//释放Lb的头结点*Lb = NULL;
}

二、稀疏多项式的相加和相乘

假设有两个多项式
f 1 ( x ) = 7 + 3 x + 9 x 8 + 5 x 17 f_1(x)=7+3x+9x^8+5x^{17} f1(x)=7+3x+9x8+5x17
f 2 ( x ) = 8 x + 22 x 7 − 9 x 8 f_2(x)=8x+22x^7-9x^8 f2(x)=8x+22x79x8
多项式的通项公式为
P n ( x ) = p 1 x e 1 + p 2 x e 2 + ⋯ + p m x e m P_n(x)=p_1x^{e_1}+p_2x^{e_2}+\cdots+p_mx^{e_m} Pn(x)=p1xe1+p2xe2++pmxem
利用线性表P表示,则
线性表 P = ( ( p 1 , e 1 ) , ( p 2 , e 2 ) , ⋯ , ( p m , e m ) ) 线性表P=((p_1,e_1),(p_2,e_2),\cdots,(p_m,e_m)) 线性表P=((p1,e1),(p2,e2),,(pm,em))
f 1 ( x ) 和 f 2 ( x ) 分别用线性表 A 和 B 表示 f_1(x)和f_2(x)分别用线性表A和B表示 f1(x)f2(x)分别用线性表AB表示
线性表 A = ( ( 7 , 0 ) , ( 3 , 1 ) , ( 9 , 8 ) , ( 5 , 17 ) ) 线性表A=((7,0),(3,1),(9,8),(5,17)) 线性表A=((7,0),(3,1),(9,8),(5,17))
线性表 B = ( ( 8 , 1 ) , ( 22 , 7 ) , ( − 9 , 8 ) ) 线性表B=((8,1),(22,7),(-9,8)) 线性表B=((8,1),(22,7),(9,8))
假设使用顺序表实现多项式的相加

算法步骤

  1. 创建一个新数组c
  2. 分别从头遍历比较a和b的每一项
    指数相同,对应系数相加,若其和为零,则比较两个表的下一项,若其和不为零,则在c中增加一个新项
    指数不相同,则将指数比较小的项复制到c中
  3. 一个多项式遍历完毕时,将另一个剩余项依次复制到c中

那么,数组c的大小如何确定?由于无法确定数组c的大小,所以这里不使用顺序表实现,而是用单链表实现。
定义多项式的结点及其结构

//定义多项式结点
struct PolyNode
{float coef; //系数int   expn; //指数struct PolyNode* next;
};
//定义多项式结点指针类型
typedef struct PolyNode* PPolyNode;
//定义多项式类型
typedef struct PolyNode* PolyLinkList;

2.1 稀疏多项式的相加

算法步骤:

  1. 指针p1和p2初始化,分别指向Pa和Pb的首元结点
  2. p3指向和多项式的当前结点,初值为Pa的头结点
  3. 当指针p1和p2均为到达表尾时,则循环比较p1和p2所指结点的指数值
  4. p1->expn 与 p2->expn分3种情况:
    当p1->expn == p2->expn是,则将两个结点中的系数相加
    若和不为零,则修改p1所指结点的系数值,同时删除p2所指结点
    若和为零,则删除p1和p2所指结点
    当p1->expn < p2->expn时,则取p1所指结点插入到和多项式链表中
    当p1->expn > p2->expn时,则取p2所指结点插入到和多项式链表中
  5. 将非空表的剩余结点插入到p3所指结点的后面
  6. 释放Pb的头结点

代码实现如下

void poly_add(PolyLinkList* Pa, PolyLinkList* Pb, PolyLinkList* Pc)
{PPolyNode p1 = (*Pa)->next;    //指向Pa链表的首元结点PPolyNode p2 = (*Pb)->next;    //指向Pb链表的首元结点PPolyNode p3 = *Pa;			  //指向Pa的头结点,作为和多项式链表	*Pc = *Pa;PPolyNode q = NULL;		     //指向要被删除的结点		while (p1 && p2){if (p1->expn == p2->expn)		//p1指数等于p2指数{float coef = p1->coef + p2->coef;if (coef)		//不为零{//修改p1所指结点的系数p1->coef = coef;p3->next = p1;p3 = p1;p1 = p1->next;}else          //为零{//删除p1所指结点q = p1;p1 = p1->next;free(q);q = NULL;}//删除p2所指结点q = p2;p2 = p2->next;free(q);q = NULL;}  else if (p1->expn < p2->expn)		//p1指数小于p2指数{//p1所指结点插入到和多项式链表p3->next = p1;p3 = p1;p1 = p1->next;}else                              //p1指数大于p2指数{//p2所指结点插入到和多项式链表p3->next = p2;p3 = p2;p2 = p2->next;}}p3->next = p1 ? p1 : p2;	//插入剩余数据元素free(*Pb);		//释放Pb头结点*Pb = NULL;
}

2.2 稀疏多项式的相乘

  1. 指针p1和p2初始化,分别指向Pa和Pb的首元结点
  2. 指针p3初始化,指向Pc的头结点,初化始时,Pc只是一个空表
  3. 用Pa的第一项与Pb的每一项相乘,将每一项相乘结果插入到Pc中(有序)
  4. 从Pa的第二项开始与Pb的每一项相乘,将每一项结果插入到Pc中(插入后有序)
    在Pc寻找插入位置
    设coef = p1->coef * p2->coef ,expn = p1->expn + p2->expn,表示当前p1和p2所指项的相乘结果
    若p3->next->expn < expn,则p3 = p3->next,直到p3->next->expn > expn,分两种情况
    若存在p3->next->expn > expn, 则新建一个结点插入到p3所指结点后
    若不存在p3->next->expn > expn,即p3->next == NULL时,则新建一个结点插入到p3所指结>点后
    若p3->next->expn == expn,分两种情况
    若p3->next->coef + coef结果为零,则删除p3->next所指结点
    若p3->next->coef + coef结果不为零,则修改p3->next所指结点的系数

代码实现如下

//逐项插入法
void poly_mul(PolyLinkList* Pa, PolyLinkList* Pb, PolyLinkList* Pc)
{PPolyNode p1 = (*Pa)->next;PPolyNode p2 = (*Pb)->next;   //p1,p2分别指向Pa和Pb的首元结点PPolyNode p3 = *Pc;			  //p3分别指向Pc的头结点	PPolyNode temp = NULL;		  //作为一个临时的结点指针if (p1)//将p1的第一项乘以Pb的每一项{while (p2){PPolyNode newNode = (PPolyNode)malloc(sizeof(struct PolyNode));if (NULL == newNode){printf("malloc fail!\n");exit(ERROR);}newNode->coef = p1->coef * p2->coef;  //p1,p2所指结点的系数相乘newNode->expn = p1->expn + p2->expn; //p1,p2所指结点的指数相乘newNode->next = NULL;p3->next = newNode;p3 = newNode;p2 = p2->next;}}//从Pa的第二项开始与Pb的每一项相乘,将每一项结果插入到Pc,直到p1到达Pa的表尾p1 = p1->next;while (p1){p2 = (*Pb)->next;p3 = *Pc;while (p2){//在Pc寻找插入位置float coef = p1->coef * p2->coef;int   expn = p1->expn + p2->expn;while (p3->next && p3->next->expn < expn)p3 = p3->next;if (p3->next && p3->next->expn == expn)   //expn与p3->next->expn相同{if (p3->next->coef + coef)	//和不为零p3->next->coef += coef;else    //和为零{//删除p3->next所指结点temp = p3->next;p3->next = temp->next;free(temp);temp = NULL;}}else   //p3->next->expn > expn 或p3->next == NULL{//在p3->next前插入一个新结点temp = (PPolyNode)malloc(sizeof(struct PolyNode));if (NULL == temp){printf("malloc fail!\n");destoryPoly(Pc);}temp->coef = coef;temp->expn = expn;temp->next = p3->next;p3->next = temp;p3 = p3->next;}p2 = p2->next;}p1 = p1->next;}
}

总结

完整代码:https://gitee.com/PYSpring/data-structure/tree/master

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/37950.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue+uniapp的超市售货管理平台

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

考研生活day2--王道课后习题2.3.1、2.3.2、2.3.3

2.3.1 题目描述&#xff1a; 这题和曾经做过的LeetCode203.移除元素一模一样&#xff0c;所以我们就使用LeetCode进行书写&#xff0c;题目链接203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; 解题思路 大家的第一反应肯定是根据书上所学的书写方法一样书写&…

【PB案例学习笔记】-26制作一个带浮动图标的工具栏

写在前面 这是PB案例学习笔记系列文章的第26篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

爬虫cookie是什么意思

“爬虫 cookie”指的是网络爬虫在访问网站时所使用的cookie&#xff0c;网络爬虫是一种自动化程序&#xff0c;用于在互联网上收集信息并进行索引&#xff0c;这些信息可以用于搜索引擎、数据分析或其他目的。 本教程操作系统&#xff1a;Windows10系统、Dell G3电脑。 “爬虫…

51-1 内网信息收集 - 内网资源探测

导语 在内网渗透过程中,通常需要利用各种技术来探测内网资源,为后续的横向渗透做准备。发现内网存活的主机及其详细信息可以帮助确定攻击方向和潜在的漏洞。 一、基于 ICMP 发现存活主机 ICMP(Internet Control Message Protocol,因特网控制消息协议)是 TCP/IP 协议簇的…

一段式、二段式和三段式状态机的特点及适用情况:

在FPGA设计中,状态机的选择主要取决于具体应用场景和设计需求。 一段式状态机: 优点: 结构简单,易于理解和实现占用资源少时序逻辑简单,延迟小 缺点: 组合逻辑复杂度高可能存在毛刺问题不易于大规模状态机的设计 适用场景: 简单的控制逻辑状态数量较少的场合对时序要求较…

React+TS前台项目实战(二十二)-- 全局常用导出组件Export封装

文章目录 前言Export组件1. 功能分析2. 代码详细注释3. 使用方式4. 效果展示 总结 前言 今天我们来封装一个带导出图标的导出组件。 Export组件 1. 功能分析 通过传入链接地址&#xff0c;规定要跳转的导出页面&#xff0c;或是直接通过链接导出数据 2. 代码详细注释 // /c…

虚拟环境管理

虚拟环境 在使用 Python 时我们一般使用“pip install 第三方包名”来安装第三方包&#xff0c;但是由于pip的特性&#xff0c;系统只能安装每个包的一个版本。而在实际开发中&#xff0c;可能同时开发多个项目&#xff0c;如&#xff1a;上图有三个项目&#xff1b;每个项目需…

django学习入门系列之第三点《BootSrap初了解》

文章目录 初识BootStrap往期回顾 初识BootStrap BootSrap是什么&#xff1f; 是别人帮我们已写好的CSS样式&#xff0c;我们如果想要使用这个BootSrap&#xff1a; 下载BootStrap使用 在页面上引入BootStrap编写HTML时&#xff0c;按照BootStrap的规定来编写 自定制 官网&…

【UE5.1】Chaos物理系统基础——02 场系统的应用

目录 步骤 一、运用临时场&#xff08;外部张力&#xff09;破裂几何体集 二、使用构造场固定几何体集 步骤 在上一篇中&#xff08;【UE5.1】Chaos物理系统基础——01 创建可被破坏的物体&#xff09;我们已经创建了可被破碎的几何体集&#xff0c;在最后我们防止几何体集…

微信小程序简历Demo

微信小程序简历Demo 使用介绍最后获取源码 bilibili视频介绍 使用介绍 使用微信小程序实现的一个简历实现Demo 拖动马里奥&#xff0c;到指定Name下方 向上顶就可以显示对应的简历样式 点击头像可拨打电话 点击信息处可显示当前位置 最后 这是一个简单并且有趣的微信小程…

Renesas MCU使用SCI_I2C驱动OLED

目录 概述 1 软硬件 1.1 软件版本信息 1.2 OLED屏幕 1.2.1 OLED简介 1.2.2 SSD1306介绍 1.2.3 0.9寸OLED模块介绍 2 FSP配置项目 2.1 配置项目参数 2.2 生成项目文件架构 3 代码实现 3.1 I2C的库函数 3.1.1 R_SCI_I2C_Open() 3.1.2 R_SCI_I2C_Read() 3.1.3 R_SCI_…

谷粒商城篇章10 -- P262-P291/P295-P310 -- 订单服务(支付)【分布式高级篇七】

目录 1 页面环境搭建 1.1 静态资源上传到nginx 1.2 SwitchHosts增加配置 1.3 网关配置 1.4 订单模块基础配置 1.4.1 引入 thymeleaf 依赖 1.4.2 application.yml配置 1.4.3 bootstrap.properties配置 1.4.4 开启nacos注册发现和远程调用 1.5 修改各个页面的静态资源路…

windows电脑开发ios的p12证书申请流程

很多同学在做ios打包的时候&#xff0c;发现ios打包需要一个p12格式的证书和一个证书profile文件&#xff0c;那么ios开发就一定需要使用mac电脑来申请ios证书吗&#xff1f;其实申请ios证书并不一定需要mac电脑&#xff0c;因为证书是一个通用的技术&#xff0c;使用普通的ssl…

Perl 语言开发(二):变量与数据类型

目录 1. 变量的基本概念 1.1 标量变量 1.2 数组变量 1.3 哈希变量 2. 数据类型详解 2.1 标量数据类型 2.1.1 数字 2.1.2 字符串 2.2 数组数据类型 2.2.1 数组操作 2.3 哈希数据类型 2.3.1 哈希操作 3. 变量的作用域与生存期 3.1 全局变量 3.2 局部变量 3.3 词法…

JavaScript将参数传递给事件处理程序

本篇文件我们将实现导航栏中&#xff0c;选中时候&#xff0c;会将您选中的进行高亮显示&#xff1b; ● 首先我们来获取我们想要的HTML元素 const nav document.querySelector(.nav);● 接着我们来写选中的高亮显示 nav.addEventListener(mouseover, function (e) { //鼠…

主干网络篇 | YOLOv5/v7 更换主干网络之 ShuffleNetv2 | 高效CNN架构设计的实用指南

主干网络篇 | YOLOv5/v7 更换主干网络之 ShuffleNetv2 | 高效CNN架构设计的实用指南 1. 简介 近年来&#xff0c;深度卷积神经网络&#xff08;CNN&#xff09;在图像识别、目标检测等领域取得了巨大进展。然而&#xff0c;随着模型复杂度的不断提升&#xff0c;模型训练和部…

申请一张含100个域名的证书-免费SSL证书

挑战一下&#xff0c;申请一张包含100个域名的证书 首先&#xff0c;我们访问来此加密网站&#xff0c;进入登录页面&#xff0c;输入我的账号密码。 登录后&#xff0c;咱们就可以开始申请证书&#xff0c;首先说一下&#xff0c;咱账号是SVIP哦&#xff0c;只有SVIP才可以申…

记一次EasyExcel的错误使用导致的频繁FullGC

记一次EasyExcel的错误使用导致的频繁FullGC 一、背景描述二、场景复现三、原因分析四、解决方案五、思考复盘 一、背景描述 繁忙的校招结束了&#xff0c;美好的大学四年也结束了&#xff0c;作者也有10个月没有更新了。拿到心仪的offer之后也开始了苦B的打工生活。 最近接到…

Python海量数据处理脚本大集合:pyWhat

pyWhat&#xff1a;精简海联数据&#xff0c;直达数据弱点要害- 精选真开源&#xff0c;释放新价值。 概览 pyWhat是Github社区上一款比较实用的开源Python脚本工具。它能够快速提取信息中的 IP 地址、邮箱、信用卡、数字货币钱包地址、YouTube 视频等内容。当你遇到了一串莫名…