【数据结构】顺序表实现的层层分析!!

news2024/11/24 23:09:26

在这里插入图片描述
关注小庄 顿顿解馋◍˃ ᗜ ˂◍

引言:本篇博客我们来认识数据结构其中之一的顺序表,我们将认识到什么是顺序表以及顺序表的实现,请放心食用~

文章目录

  • 一.什么是顺序表
    • 🏠 线性表
    • 🏠 顺序表
  • 二.顺序表的实现
    • 🏠 静态顺序表
    • 🏠 动态顺序表
      • 接口的实现
  • 三.顺序表的优缺点

一.什么是顺序表

🏠 线性表

线性表是n个有相同特性数据元素的有限序列,是一种广泛使用的数据结构,常用的数据结构有链表,顺序表,队列和栈等

特点: 线性表在逻辑结构上是线性的(一条连续的直线),但在物理结构不一定连续

理解:比如我们在排队时,我们脑海中认为我们队伍应该是排成一条直线的,实际上也应该如此,这里就是类似我们待会要讲的顺序表,但有有时不免有人会插队三五成群排在队伍左右边,类似我们线性表中的链表。

🏠 顺序表

顺序表是由一块连续的物理内存空间构成的,也就是说它的逻辑结构是线性,物理结构也是线性

那有什么结构是连续的一块的内存空间呢?

这里我们就可以用我们的数组来实现顺序表,你也可以理解为顺序表本质就是数组

二.顺序表的实现

我们一般用顺序表实现对我们的数据进行增删查改操作,来很好地运用我们的数据,顺序表一般分为静态顺序表和动态顺序表。

  • 顺序表结构的分析
    我们既然知道顺序表的本质是数组,那我们需要定义一个数组;
    其次我们要对我们的数据进行增删查改操作,那我们进行增的时候得知道我们空 间有多少容量吧,同时我们进行删除操作时也需要有“边界感”,如果不知道顺序表有没有数据就麻烦了。

因此,我们可以定义一个size来表示有效数据个数,用一个capacity代表顺序表的容量
在这里插入图片描述
注:这里由于数组下标是从0开始,所以我们的size要往前一步跟下标同步

🏠 静态顺序表

静态顺序表:使用定长数组来存储元素

静态顺序表的封装

//静态顺序表
typedef int Datatype;//相同类型元素 方便不同数据类型直接替换
#define N 100
struct Seqlist
{
	Datatype arr[N];
	int size;
	int capacity;
};

缺点: 静态顺序表的数组长度是限定的,导致无法灵活存放数据。空间大了导致浪费,空间小了导致数据丢失。

因此,在实际中,我们采用动态顺序表来操作我们的数据

🏠 动态顺序表

C语言动态内存管理工作是给我们程序员做的,给我们提供更多的灵活性,由程序员决定空间何时申请和释放。我们可利用这特点实现动态顺序表

//动态顺序表
typedef int Datatype; 
typedef struct Seqlist
{
	Datatype * arr;
	int size;
	int capacity;
}Seqlist;

接口的实现

  • 顺序表的初始化
void InitSeqlist(Seqlist* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

注:这里要传结构体指针,通过传址调用来修改size和capacity

  • 顺序表的打印
    这里就体现size的用处了,从下标0开始,到size就停止打印
void PrintSeqlist(Seqlist* ps)
{
	assert(ps->size != 0);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arr[i]);
	}
}
  • 顺序表的头插和尾插
    在这里插入图片描述

顺序表的头插和尾插我们需要解决容量问题
对于空顺序表和空间足够的顺序表我们自然无需担心,但对于size==capacity时的顺序表就需要扩容了,那该怎么扩呢?

我们有三种扩容方式:

  1. 一次扩容一个空间
  2. 一次扩容固定大小空间
  3. 成倍数扩容(1.5或2倍)
    理解:对于第一种扩容方式,有限次数扩容还好,但多次扩容会降低效率;对于第二种空间给少会数据丢失,给多会空间浪费
    最好方法就是成倍扩容,参考文章数组成倍扩容原因

因此进行尾插和头插前要判断是否扩容,不够就成倍扩

void Capacity(Seqlist* ps)
{
	assert(ps);

	int newcapacity = 0;
	if (ps->capacity == ps->size)
	{
		newcapacity = ps->capacity == 0 ? 4 : 2 * newcapacity;
		int* temp = (int*)realloc(ps->arr,newcapacity * sizeof(int));
		if(NULL == temp)
		{
		  perror("realloc failed");
		  exit(1);
		}
		ps->arr = temp;
	}
	ps->capacity = newcapacity;
}

尾插直接让size下标的空间用来赋值就可以了

void Pushtail(Seqlist* ps, Datatype x)
{
	assert(ps);
	//判断是否要扩容
	Capacity(ps);
	ps->arr[ps->size++] = x;
}

注:插入数据,size代表的有效数据个数也要增加

头插要先实现数据的左移再插入

void Pushhead(Seqlist* ps, Datatype x)
{
	assert(ps);
	//判断容量问题
	Capacity(ps);
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;
	ps->size++;
}
  • 顺序表的头删和尾删
    请思考一个问题,清除数据,是否一定要删除这个数据?
    当然不是的,我们用不了这个数据使它失效也是可以的

尾删

void Deltail(Seqlist* ps)
{
	assert(ps->size);
	assert(ps);
	ps->size--;
}

头删直接左移数据再使数据无效即可

void Delhead(Seqlist* ps)
{
	assert(ps->size);
	assert(ps);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
	//删除数据不代表一定要删除
}

注:删除数据,要使size代表的有效数据个数对应减少

  • 指定位置删除数据和指定位置之前插入数据

删除数据注意size–就可以了,直接循环遍历到pos位置

void PosDel(Seqlist* ps, int pos)
{
	assert(ps);
	assert(ps->size);
	assert(pos > 0&&pos<=ps->size);
	//pos等于size
	if (pos == ps->size)
	{
		ps->size--;
		return;
	}
	for (int i = pos - 1; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

注意 pos与下标差了1 还有pos的合法性

指定位置插入数据也是可以按照循环移动数据但要注意容量问题

void PosPush(Seqlist* ps, Datatype x, int pos)
{
	assert(ps);
	//要确保插入位置的合法性
	assert(pos >= 0 && pos < ps->size);
	int i = 0;
	Capacity(ps);
	for (i = ps->size; i > pos-1; i--)
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[pos-1] = x;
	ps->size++;
}

注意 pos合法性和下标关系

延伸:对于指定位置的插入和删除也可以采用memmove来实现

//顺序表的指定位置插入(memmove实现)
void SLInsert1(SL* ps, int pos, Datatype x)
{
	assert(ps);
	//要确保插入位置的合法性
	assert(pos >= 0 && pos < ps->size);
	Datatype arr2[1] = { 0 };
	arr2[0] = x;
	memmove(ps->arr+pos+1,ps->arr+pos,(ps->size-pos)*sizeof(Datatype));
	memmove(ps->arr + pos, arr2, 4);
	ps->size++;//记得插入后size要增加
}

//顺序表指定位置的删除(memmove)
void SLErase1(SL* ps, int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	memmove(ps->arr+pos,ps->arr+pos+1,(ps->size-pos-1)*sizeof(Datatype));
	ps->size--;
}
  • 查找数据
    直接遍历即可
void SLFind(Seqlist* ps, Datatype x)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
		{
			printf("找到了下标为%d", i);
			return;
		}
	}
	printf("没找到!");
	return;
}

三.顺序表的优缺点

到这里我们的顺序表基本实现完了,我们分析一下他的优缺点

优点
1.利用数组下标支持随机访问
2.数组空间连续,cpu高速缓存命中率高

缺点
1.进行插入和删除时移动数据效率低下
2.扩容可能造成空间浪费和数据丢失
3.扩容要申请空间拷贝数据,有不小的消耗

总结:顺序表适用于频繁访问和元素高效存储的应用场景

那有什么方法可以解决顺序表暴露的问题呢?请听下回的链表~


本次分享到这就结束了,不妨来个一键三连呀~

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

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

相关文章

ShardingSphere 5.x 系列【14】广播表、单表

有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址:https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1.广播表1.1 概述1.2 案例演示1.2.1 环境准备1.2.2 配置1.2.3 测试2. 单表2.…

2024年.NET框架发展趋势预测

.NET框架仍然是全球开发人员的编程基石&#xff0c;为构建广泛的应用程序提供了一个通用的、强大的环境。微软对创新的坚定承诺见证了.NET的发展&#xff0c;以满足技术领域不断变化的需求。今年&#xff0c;在更广泛的行业运动、技术进步和开发者社区反馈的推动下&#xff0c;…

记一次:Python的学习笔记五(Django集成swagger)

上一篇集成在了gatway上了&#xff0c;但给别人使用swagger的时候还是没有文档&#xff0c;如何集成swagger呢&#xff1f; python版本&#xff1a;Python 3.11.5 Django版本&#xff1a;4.2.7 0、Swagger 文档介绍 Swagger 是一种用于 RESTful API 的开源框架&#xff0c;…

2种方法,教你使用Python实现接口自动化中的参数关联

通常在接口自动化中&#xff0c;经常会参数关联的问题&#xff0c;那么什么是参数关联&#xff1f; 参数关联就是上一个接口的返回值会被下一个接口当做参数运用&#xff0c;其中Python中可以实现参数关联的方法有很多种&#xff0c;今天小编给大家介绍下&#xff0c;如何通过…

SQL Server ID 自增不连续、删除数据后再次插入ID不连续

背景 当我们使用SQL Server 进行数据库操作时&#xff0c;经常会把 Table 的 ID 设置成主键自增 PRIMARY KEY IDENTITY&#xff0c;但是这样做存在一个问题就是 当我们删除一行数据后&#xff0c;再次添加后会看到ID的顺序不连续&#xff0c;如下所示。 查询一下&#xff1a;…

冲突管理最佳实践

任何团队都无法避免冲突&#xff0c;如何有效管理冲突&#xff0c;将冲突转化为团队成长和凝聚的动力&#xff0c;是任何一个团队管理者的必修课。原文: Best Practices for Managing Conflict in Engineering Management Obie Fernandez Unsplash 冲突在任何组织中都不可避免&…

排序第三篇 直接插入排序

插入排序的基本思想是&#xff1a; 每次将一个待排序的记录按其关键字的大小插入到前面已排好序的文件中的适当位置&#xff0c; 直到全部记录插入完为止。 一 简介 插入排序可分为2类 本文介绍 直接插入排序 它的基本操作是&#xff1a; 假设待排充序的记录存储在数组 R[1……

【鸿蒙 HarmonyOS 4.0】状态管理

一、介绍 资料来自官网&#xff1a;文档中心 在声明式UI编程框架中&#xff0c;UI是程序状态的运行结果&#xff0c;用户构建了一个UI模型&#xff0c;其中应用的运行时的状态是参数。当参数改变时&#xff0c;UI作为返回结果&#xff0c;也将进行对应的改变。这些运行时的状…

【Linux】普通用户sudo失败怎么办

普通用户&#xff0c;sudo失败报错怎么办 问题分析如何解决成功 问题分析 新建的普通用户sudo失败 sudo提权&#xff0c;是以root的身份执行命令。 当我们用sudo提升权限的时候&#xff0c;这里有个问题&#xff0c;Linux会提示我们输入当前普通用户的密码——这就有点不好。…

骨传导耳机哪个品牌比较好?精选五大倍受好评的机型推荐!

近几年大家对保护听力健康的意识也越来越强烈了&#xff0c;骨传导耳机作为保护听力健康的不二之选&#xff0c;使用的人也越来越多&#xff0c;但是&#xff0c;在面对市场上鱼龙混杂的产品时&#xff0c;还是有很多人不知道该怎么去挑选一款性能优秀的骨传导耳机&#xff0c;…

[TCP] TCP/IP 基础知识词典(2)

我想统计一下&#xff0c;TCP/IP 尤其是TCP协议&#xff0c;能搜到的常见的问题&#xff0c;整理起来&#xff0c;关键词添加在目录中&#xff0c;便于以后查阅。 目前预计整理共3篇&#xff1a; [TCP] TCP/IP 基础知识问答 &#xff1a;基础知识 [TCP] TCP/IP 基础知识问答&…

硬盘坏了数据恢复怎么做?记好这2个方法!

“前段时间我的电脑硬盘出了点问题&#xff0c;不知道为什么就坏了。硬盘坏了数据恢复应该怎么做呢&#xff1f;请大家分享几个好用的方法吧&#xff01;” 在数字化时代&#xff0c;硬盘作为数据存储的核心组件&#xff0c;其重要性不言而喻。然而&#xff0c;硬盘损坏是一个常…

【知识分享】自动化测试首选接口自动化?

在分层测试的“金字塔”模型中&#xff0c;接口测试属于第二层服务集成测试范畴。 相比UI自动化测试而言&#xff0c;接口自动化测试收益更大&#xff0c;且容易实现&#xff0c;维护成本低&#xff0c;有着更高的投入产出比。因此&#xff0c;项目开展自动化测试的首选一般为接…

记阿里云mysql丢表丢数据的实践记录

第一时间挂工单&#xff0c;联系工程师指引&#xff0c;现在回过来想&#xff0c;第一时间要确认发生时间。 1.通过性能视图&#xff08;马后炮的总结&#xff0c;实际凭记忆恢复了三四次才找到数据&#xff09; 2.先恢复数据 通过Navicat工具&#xff0c;结构同步&#xff0…

Vscode vim 插件使用Ctrl+C和V进行复制粘贴到剪切板

Vscode vim 插件使用CtrlC和V进行复制粘贴到剪切板 使用这一个插件的时候复制粘贴和其他软件互动的时候体验不好, 并且不可以用Ctrl c, Ctrl v很不爽 "vim.commandLineModeKeyBindings": [{"before" : ["Ctrl", "c"],"after&q…

C#,动态规划(DP)丢鸡蛋问题(Egg Dropping Puzzle)的三种算法与源代码

1 扔鸡蛋问题 动态规划&#xff08;Dynamic Programming&#xff0c;DP&#xff09;是运筹学的一个分支&#xff0c;是求解决策过程最优化的过程。20世纪50年代初&#xff0c;美国数学家贝尔曼&#xff08;R.Bellman&#xff09;等人在研究多阶段决策过程的优化问题时&#xf…

3.deeplabv3+的深层网络结构的实现

在第一篇文章中我们提到“在encoder部分&#xff0c;主要包括了backbone&#xff08;DCNN&#xff09;、ASPP两大部分”&#xff0c;在这里的backbone就是mobilenetv2网络结构和xception网络结构&#xff0c;而ASPP结构就是深层网络结构&#xff0c;其网络结构如下&#xff1a;…

Anaconda和TensorFlow环境搭建!!

Anaconda下载 进入官网下载 https://www.anaconda.com/download 也可以通过清华的映像站下载&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 我这里下载的是3.4.20版本。下载好就可以安装默认安装就行。 打开Anaconda Prompt修改成国内镜像 conda c…

Verilog刷题笔记36

题目&#xff1a; Create a 4-bit wide, 256-to-1 multiplexer. The 256 4-bit inputs are all packed into a single 1024-bit input vector. sel0 should select bits in[3:0], sel1 selects bits in[7:4], sel2 selects bits in[11:8], etc. 我的解法&#xff1a; module …

【蜂窝物联】医院WiFi全覆盖解决方案

项目背景 随着信息化程度的普及,无线网络覆盖的需求显得愈发突出&#xff0c;移动通信&#xff08;GSM&#xff0c;3G&#xff0c;4G&#xff09;的网络在很多区域无法满足客户的速率要求&#xff0c;而且不能满足某些特定场景的业务需求。医院是人流密集场所&#xff0c;进行…