线性表——(2)线性表的顺序存储及其运算的实现

 

归纳编程学习的感悟,
记录奋斗路上的点滴,
希望能帮到一样刻苦的你!
如有不足欢迎指正!
共同学习交流!
🌎欢迎各位→点赞 👍+ 收藏⭐ + 留言​📝
     看到美好,感受美好,屏蔽阴霾!

一起加油!

目录

 

一、顺序表:

 二、顺序表基本运算的实现:

💦顺序表的初始化:

💦插入运算 :

☘️顺序表的数据元素的插入算法:

💦删除运算: 

☘️顺序表的数据元素的删除算法:

💦按值查找 :

☘️顺序表的数据元素查找算法:

三、顺序表的其他运算举例:

💦例1:

☘️顺序表的划分算法: 

 💦例2:

☘️顺序表的合并算法:

 💦例3:

☘️两个顺序表的比较算法: 

四、总结: 

五、共勉:


一、顺序表:

        线性表的顺序存储是指在内存中用地址连续的一块存储空间顺序存放线性表中的各数据元素,用这种存储形式存储的线性表称为顺序表。因为内存中的地址空间是线性的,所以用物理位置关系上的相邻性实现数据元素之间的逻辑相邻关系既简单又自然。线性表的顺序存储示意图如图 A所示,设 a 的存储地址为 Loc(a),每个数据元素占 d 个存储单元,则第 i个数据元素的地址为:

Loc(a^{_{i}})=Loc(a^{_{1}})+(i-1)*d       1<=i<=n

图A  线性表的顺序存储示意图

         这就是说,只要知道顺序表首地址每个数据元素所占存储单元的个数就可求出第 i 个数据元素的地址,这也是顺序表具有按数据元素的序号随机存取的特点
        在程序设计语言中,一维数组在内存中占用的存储空间就是一组连续的存储区域,因此,用一维数组来表示顺序表的数据存储区域是再合适不过的了。考虑到线性表有插入、删除等运算,即表长是可变的,因此,数组的容量要设计得足够大,设用 data[MAXSIZE]来表示,其中 MAXSIZE是一个根据实际问题定义的足够大的整数,线性表中的数据元素从 data[0]开始依次顺序存放,但当前线性表中的实际数据元素个数可能未达到 MAXSIZE 个,因此需用变量 last 记录当前线性表中最后一个数据元素在数组中的位置,即 last 具有指针的作用,始终指向线性表中最后一个数据元素,因此,表空时 last =-1。这种存储思想的具体描述可以是多样的,如可以是:

datatype data[MAXSIZE];
	int last;

        这样表示的顺序表如图 A 所示,表长为 last+1,数据元素分别存放在 data[0]到 data[last]中这样使用简单方便,但有时不便于管理。

        从结构性上考虑,通常将 data 和 last 封装成一个结构,作为顺序表的数据类型: 

typedef struct{
	datatype data[MAXSIZE];
	int last;
}SeqList; 

         定义一个顺序表:

SeqList L

        这样表示的线性表如图(a) 所示。表长 = L.last+1,线性表中的数据元素 a1至 an分别存放在 L.data[0]至 L.data[L.last]中.其实有时定义一个指向 SeqList 类型的指针更为方便: 

SeqList *L

        L是一个指针变量,线性表的存储空间通过 L=malloc(sizeof(SeqList)运算来获得。L 中存放的是顺序表的地址,这样表示的线性表如图 (b) 所示。表长表示为(*L).last+1 或 L->last+1,线性表的存储区域为 L->data,线性表中数据元素的存储空间为: 

L->data[0] ~ L->data[L->last]

 

 二、顺序表基本运算的实现:

        根据以上线性表顺序存储结构定义,确定了其存储方式之后,就可以讨论其基本运算的实现方法(即实现算法)了,同时还要对算法进行初步的分析。

💦顺序表的初始化:

        顺序表的初始化构造一个空表,这对顺序表是一个加工型的运算,因此,将L设为指针参数,首先动态分配存储空间,然后将表中 last 指针置为-1,表示顺序表中没有数据元素。算法如下:

SeqList *init_SeqList(){ 
	SeqList *L;
	L=malloc(sizeof(SeqList));
	L->last=-1;
	return L;
}

        设调用函数为主函数,主函数对初始化函数的调用如下: 

main(){
	SeqList *L;
	L=init_SeqList();
	…… 
} 

💦插入运算 :

        线性表的插入是指在表的第 i个位置上插入一个值为x 的新数据元素,插入后使原表长为 n的线性表 (ai, a2,…,ai-1,ai, ai+1,…,an) 成为表长为n+1 的线性表 (a1,a2,…,ai-1,x,ai, ai+1,…,an)。i的取值范围为1<=i<=n+1。
在顺序表上完成插入运算通过以下步骤进行:
将 ai~an顺序向后移动,为新数据元素让出位置;
将x置入空出的第i个位置;
修改 last 指针 (相当于修改表长),使之仍指向最后一个数据元素。
图B所示为顺序表中的插入运算示意图。

图B  顺序表中的插入运算示意图

☘️顺序表的数据元素的插入算法:

int Insert_SeqList(SeqList *L,int i,datatype x){
	int j;
	if(L->last==MAXSIZE-1){
		printf("表满");return -1;//表空间已满,不能插入 
	}
	if(i>L->last+2||i<1){//检查插入位置的正确性 
		printf("位置错");return 0; 
	}	
	for(j=L->last;j>=i-1;j--){
		L->data[j+1]=L->data[j];//节点移动 
	} 
	L->data[i-1]=x;//新数据元素插入 
	L->last++;//last指针仍指向最后一个数据元素 
	return 1;
}

        在本算法中应注意以下问题:

  • ⚡顺序表中数据区域有 MAXSIZE 个存储单元,所以向顺序表中插入新数据元素时应先检查表空间是否满了,在表满的情况下不能再进行插入运算,否则会产生溢出错误。
  • 要检验插入位置的有效性,这里i的有效范围是 1<=i<=n+1,其中 n 为原表长。
  • 注意数据的移动方向

        🔑插入算法的时间复杂度分析:顺序表的插入运算,时间主要消耗在数据的移动上,在第i个位置上插入X,从ai到an都要向后移动一个位置,共需要移动n-i+1个数据元素,而i的取值范围为1<=i<=n+1,即有n +1个位置可以插入。设在第i个位置上进行插入运算的概率为 pi,则平均移动数据元素的次数为:

        E_{in}=\sum_{i=1}^{n+1}p_{i}(n-i+1)

假设在第i个位置进行插入运算的可能性为等概率情况,即pi=1/(n+1),则 

E_{in}=\frac{1}{n+1}\sum_{i=1}^{n+1}(n-i+1)=\frac{n}{2}

这说明在顺序表上进行插入运算,需平均移动表中一半的数据元素。显然其时间复杂度为O(n). 

💦删除运算: 

        线性表的删除运算是指将表中第i个数据元素从线性表中去掉,删除后使原表长为 n的线性表 (a1,a2,…,ai-1,ai,ai+1,…,an)成为表长为n-1的线性表 (a1,a2,…,ai-1,ai+1,…,an),i的取值范围为1<=i<=n。
        在顺序表上完成删除运算的步骤如下:

将ai+1~an顺序向前移动;

修改 last 指针(相当于修改表长),使之仍指向最后一个数据元素。

图C所示为顺序表中的删除运算示意图。 

图C  顺序表中的删除运算示意图

☘️顺序表的数据元素的删除算法:

int Delete_SeqList(SeqList *L,int i){
	int j;
	if(i<1||i>L->last+1){
		printf("不存在第i个数据元素");return 0;//检查空表及删除位置的合法性 
	}
	for(j=i;j<L->List;j++){
		L->data[i-1]=L->data[i];//向上移动 
	}
	L->last--;
	return 1;//删除成功 
} 

        本算法注意以下问题:

⚡删除第i个数据元素,i的取值为1<=i<=n,否则第个数据元素不存在,因此,要检查删
除位置的有效性。

当表空时不能进行删除运算,因表空时 L->last 的值为-1,条件(1 >L->last+1)也包括了对表空的检查。 

删除a之后,该数据已不存在,如果需要,先取出 a,再进行删除。

        🔑删除算法的时间复杂度分析: 与插入运算相同,删除运算的时间主要消耗在移动表中数据元素上,删除第i个数据元素时,其后面的数据元素 ai+1~an都要向前移动一个位置,共移动了n-i 个数据元素,所以平均移动数据元素的次数为:

E_{de}=\sum_{i=1}^{n}p_{i}(n-i)

同样,在删除位置等概率情况下,pi=1/n,则

E_{de}=\frac{1}{n}\sum_{i=1}^{n+1}(n-i)=\frac{n-1}{2}

        这说明在顺序表上做删除运算时大约平均需要移动表中一半的数据元素。显然,该算法的时间复杂度为 O(n)。

💦按值查找 :

        线性表中的按值查找是指在线性表中查找与给定值 x 相等的数据元素。在顺序表中完成该运算最简单的方法是:从第一个数据元素 a 起依次和x进行比较,直到找到一个与x相等的数据元素,则返回它在顺序表中的存储下标或序号(二者差一);或者查遍整个表都没有找到与x相等的数据元素,返回-1。

☘️顺序表的数据元素查找算法:

int Location_SeqList(SeqList *L,datatype x){
	int i=0;
	while(i<=L.last&&L->data[i]!=x){
		i++;
	}
	if(i>L->last){
		return -1; 
	}
	else return i;//返回的是存储位置 
}

        本算法的主要运算是比较,显然比较的次数与 x 在表中的位置有关,也与表长有关。当 a1=x时,比较一次成功。当 an=x 时,比较n 次成功。其平均比较次数为(n+1)/2,时间复杂度为 O(n)。 

三、顺序表的其他运算举例:

💦例1:

        将顺序表 (a1, a2,…,an)重新排列为以a1为界的两部分: a1前面的值均比 a1 小,a1后面的值均比 a1大(这里假设数据元素的类型具有可比性,不妨设为整型),运算前后如图D
所示。这一运算称为划分,a1称为基准。

        划分的方法有多种,下面介绍的划分算法思路简单,但性能较差

        基本思路:从第二个数据元素开始到最后一个数据元素,逐一向后扫描

当前数据元素 ai比 a1大时,表明它已经在 a1的后面,不必改变它与 a1之间的位置,继续比较下一个。

若当前数据元素比 a1小,说明它应该在 a1的前面,此时将它前面的数据元素依次向后移动一个位置,然后将它置于最前面。

☘️顺序表的划分算法: 

void partition(SeqList *L){
	int i,j;
	datatype x,y;
	x=L->data[0];//将基准置于x中 
	for(i=1;i<L->last;i++){
		if(L->data[i]<x){//当前数据元素小于基准 
			y=L->data[i];
			for(j=i-1;j>0;j--){//移动 
				L->data[j+1]=L->data[j];
			}
			L->data[0]=y;
		}
	}
} 

 💦例2:

        设有顺序表 A 和 B,其数据元素均按从小到大的顺序排列,将它们合并成一个顺序表 C,要求C的数据元素也从小到大排列。
        算法思路:依次扫描 A和B 的数据元素,比较 A、B 当前数据元素的值,将值较小的数据元素赋给 C,如此直到一个线性表扫描完毕最后将未扫描完顺序表中的余下部分赋给 C 即可。C的容量要能够容纳 A、B两个线性表长度的和。

☘️顺序表的合并算法:

void merge(SeqList A,SeqList B,SeqList *C){
	int i,j,k;
	i=j=k=0;
	while(i<=A.last&&j<=B.last){
		if(A.data[i]<B.data[i]){
			C->data[k++]=A.data[i++];
		}
		else{
			C->data[k++]=B.data[j++];
		}
	}
	while(i<=A.last){
		C->data[k++]=A.data[i++];
	}
	while(j<B.last){
		C->data[k++]=B.data[j++];
	}
	C->last=k-1; 
} 

上述算法的时间复杂度是 O(m+n),其中,m是A的表长,n是 B 的表长。 

 💦例3:

        两个线性表的比较运算。假定两个线性表的比较方法如下:设A、B 是两个线性表,表长分别为 m和n。A'和 B'分别为 A 和B 中除去最大共同前缀后的子表。例如,A= (x,y,y,z,x,z),B= (x,y,y,z,y,x,x,z),两表最大共同前缀为 (x,y,y,z)。则A'=(x,z),B'= (y,x,x,z)。若A'=B'=空表,则A=B。若A'=空表且B!=空表,或两者均不为空表且A'的首数据元素小于 B’的首数据元素,则A<B;否则,A>B。
        算法思路: 首先找出A、B 的最大共同前缀,然后求出 A'和 B,再按比较规则进行比较,A>B函数返回1;A=B 返回0:A<B 返回-1。

☘️两个顺序表的比较算法: 

int compare(int A[],int B[],int m,int n){
	int i=0,j,AS[],BS[],ms=0,ns=0;//AS,BS作为A'B' 
	while(A[i]=B[i]){//找出最大共同前缀 
		i++;
	}
	for(j=i;j<m;j++){//求A',ms为A'的长度 
		AS[j-i]=A[j];
		ms++;
	}
	for(j=i;j<n;j++){//求B',ns为B'的长度 
		BS[j-i]=B[j];
		ns++;
	}
	if(ms==ns&&ms==0){
		return 0;
	}
	else if(ms==0&&ns>0||ms>0&&ns>0&&AS[0]<BS[0]){
		return -1;
	}
	else{
		return 1;
	}
}

上述算法的时间复杂度是 O(m+n)。 

四、总结: 

 学会顺序标的初始化,熟练掌握顺序表各种算法了基本结构。

五、共勉:

        以上就是我对线性表——(2)线性表的顺序存储及其运算的实现的理解,希望本篇文章对你有所帮助,也希望可以支持支持博主,后续博主也会定期更新学习记录,记录学习过程中的点点滴滴。如果有不懂和发现问题的小伙伴,请在评论区说出来哦,同时我还会继续更新对线性表的理解,请持续关注我哦!!! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ucharts中,当数据为0时,不显示

当为0时&#xff0c;会显示出来&#xff0c;值比较小的时候&#xff0c;数据会显示在一起&#xff0c;不美观 期望效果&#xff1a; 实现步骤&#xff1a; 我是将uCharts插件下载导入到src/uni_modules下的 1、修改src/uni_modules/qiun-data-charts/js_sdk/u-charts/confi…

数据结构day4作业

1.单链表任意位置删除 datetype pos;printf("please input pos");scanf("%d",&pos);headdelete_all(head,pos);Output(head);Linklist delete_all(Linklist head,datetype pos) {if(pos<1||pos>length(head)||headNULL)return head;if(head->…

Spring boot命令执行 (CVE-2022-22947)漏洞复现和相关利用工具

Spring boot命令执行 (CVE-2022-22947)漏洞复现和相关利用工具 名称: spring 命令执行 (CVE-2022-22947) 描述: Spring Cloud Gateway是Spring中的一个API网关。其3.1.0及3.0.6版本&#xff08;包含&#xff09;以前存在一处SpEL表达式注入漏洞&#xff0c;当攻击者可以访问A…

数据结构 / day06 作业

1.下面的代码打印在屏幕上的值是多少? /下面的代码打印在屏幕上的值是多少?#include "stdio.h"int compute_data(int arr[], unsigned int len) {long long int result 0;if(result len)return arr[0];resultcompute_data(arr,--len);printf("len%d, res…

基于单片机智能液位水位监测控制系统

**单片机设计介绍&#xff0c; 基于单片机智能液位水位监测控制系统 文章目录 一 概要特点应用场景工作原理实现方式 系统功能实时监测控制调节报警功能数据记录与分析 总结 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 ## 系统介绍 基于单片机…

【Python】yaml.safe_load()函数详解和示例

在Python中&#xff0c;PyYAML库提供了对YAML&#xff08;YAML Ain’t Markup Language&#xff09;文件的强大支持。YAML是一种直观的数据序列化标准&#xff0c;可以方便地存储和加载配置文件、数据日志等。 yaml.safe_load和yaml.load是Python的PyYAML库提供的两个函数&…

uniapp开发小程序使用axios进行网络请求 uniapp 小程序调试

前言 本篇最好放到项目的【README.md】文件中,方便每次发布的时候检查纠错,毕竟好记性不如烂笔头。而且其他开发者帮忙修改bug、发布新版本的时候,只需要根据这个事项就能实现整个流程的提审发布,提高效率。 1、微信小程序配置 1.1、检查APPID是否正确 测试:wx--------…

函数学习 PTA 1使用函数输出一个整数的逆序数;3判断满足条件的三位数;5使用函数求余弦函数的近似值

其实一共有五道题&#xff0c;但那两道实在太过简单&#xff0c;也不好意思打出来给大家看&#xff0c;那么这篇博客&#xff0c;就让我一次性写三道题吧&#xff01;也当是个小总结&#xff0c;睡前深思。 6-1 使用函数输出一个整数的逆序数 本题要求实现一个求整数的逆序数的…

vuepress-----6、时间更新

# 6、时间更新 基于Git提交时间修改文字时间格式 moment # 最后更新时间 # 时间格式修改 下载库文件 yarn add momentconst moment require(moment); moment.locale(zh-cn)module.exports {themeConfig: {lastUpdated: 更新时间,},plugins: [[vuepress/last-updated,{trans…

智能优化算法应用:基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于群居蜘蛛算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.群居蜘蛛算法4.实验参数设定5.算法结果6.参考…

【Vue】【uni-app】实现工单列表项详情页面

这次主要实现的是一个工单详情页面 从工单列表项中点击详情 跳转到工单详情页面&#xff0c;这个详情页面就是这次我们要实现的页面&#xff0c;并可以通过点击这个关闭按钮返回到工单列表页面 首先是在我们原有的工单列表页面的按钮增加一个点击跳转 <button size"m…

微服务API网关Spring Cloud Gateway实战

概述 微服务网关是为了给不同的微服务提供统一的前置功能&#xff1b;网关服务可以配置集群&#xff0c;以承载更多的流量&#xff1b;负载均衡与网关互相成就&#xff0c;一般使用负载均衡&#xff08;例如 nginx&#xff09;作为总入口&#xff0c;然后将流量分发到多个网关…

504. 七进制数

这篇文章会收录到 : 算法通关第十三关-青铜挑战数学基础问题-CSDN博客 七进制数 描述 : 给定一个整数 num&#xff0c;将其转化为 7 进制&#xff0c;并以字符串形式输出。 题目 : LeetCode 504. 七进制数 : 504. 七进制数 分析 : 我们先通过二进制想一下7进制数的变化特…

C++二分查找算法:包含每个查询的最小区间

题目 给你一个二维整数数组 intervals &#xff0c;其中 intervals[i] [lefti, righti] 表示第 i 个区间开始于 lefti 、结束于 righti&#xff08;包含两侧取值&#xff0c;闭区间&#xff09;。区间的 长度 定义为区间中包含的整数数目&#xff0c;更正式地表达是 righti -…

<蓝桥杯软件赛>零基础备赛20周--第8周第1讲--十大排序

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…

【C语言】把歌词里的播放时间跟歌词提取出来

一&#xff0c;介绍 给到一个字符串&#xff0c;里面包含了时间&#xff08;唱该歌词的时间以及该歌词&#xff09;例如“[02:16.33][04:11.44][05:11.44]我想大声宣布对你依依不舍”&#xff0c;如何把两者都给打印出来呢&#xff1f;下面给出解释 二&#xff0c;代码 #incl…

【Openstack Train安装】四、MariaDB/RabbitMQ 安装

本章介绍了MariaDB/RabbitMQ的安装步骤&#xff0c;MariaDB/RabbitMQ仅需要在控制节点安装。 在安装MariaDB/RabbitMQ前&#xff0c;请确保您按照以下教程进行了相关配置&#xff1a; 【Openstack Train安装】一、虚拟机创建 【Openstack Train安装】二、NTP安装 【Opensta…

UI自动化测试的正确姿势 —— Airtest设备连接API详解第一篇

一、背景 Airtest作为一款优秀的自动化测试工具&#xff0c;有着强大的API功能&#xff0c;处理日常自动化测试过程中需要的各类操作。今天就给大家逐一介绍关于设备连接和常用API部分&#xff0c;结合自动化测试中的各类需求&#xff0c;看看如何通过使用Airtest来快速实现。…

记录创建粒子的轻量级JavaScript库——particles.js(可用于登录等背景显示)

文章目录 前言一、下载particles.js二、引入particles.js并使用三、配置数据说明如有启发&#xff0c;可点赞收藏哟~ 前言 本文记录使用创建粒子的轻量级JavaScript库 particles.js 可用于登录等背景显示 一、下载particles.js 先下载particles.js库&#xff0c;放在项目libs…

【古月居《ros入门21讲》学习笔记】08_发布者Publisher的编程实现

目录 说明&#xff1a; 1. 话题模型 图示 说明 2. 实现过程&#xff08;C&#xff09; 创建功能包 创建发布者代码&#xff08;C&#xff09; 配置发布者代码编译规则 编译并运行 编译 运行 3. 实现过程&#xff08;Python&#xff09; 创建发布者代码&#xff08;…