初阶数据结构【2】--顺序表(详细且通俗易懂,不看一下吗?)

本章概述

  • 线性表
  • 顺序表
  • 顺序表问题与思考
  • 彩蛋时刻!!!

线性表

  • 概念一些在逻辑上成线性关系的数据结构的集合线性表在逻辑上一定成线性结构,在物理层面上不一定成线性结构。常见的线性表:顺序表,链表,栈,队列,字符串……。
  • 逻辑线性结构就是人为想像的具有某种联系的结构,这种关系是线性的。如图所示:在这里插入图片描述
  • 线性物理结构在空间上是连续的,是线性的,就像火车一样,各个车厢是一节一节的连接的。反之,就是非线性物理结构。在内存中的体现就是地址空间是连续的,如图所示:在这里插入图片描述
  • 为什么有的线性表物理上不是线性结构呢?:这就好比我们在一家餐馆排队取餐一样,我们都各自排好队,人与人之间可能并不是紧挨着排队,我们之间会前后错落,这就导致我们在物理空间上不是连续的,不是线性的。但是,我们在逻辑上是线性的,因为我们都是前后交错的,不能乱插队。如图所示:在这里插入图片描述
    线性表是这些在逻辑上成线性结构的数据结构的统称,就像苹果,西瓜,香蕉……这些都统称为水果,线性表也是这个意思。其它线性数据结构,我会不断的给大家分享的,继续往后学习,你就会体会到这种线性存储数据的巧妙之处。

顺序表

  • 概念在逻辑和物理上都成线性关系的数据结构它是以数组为底层来进行数据存储的,所以在物理上体现线性。 如图所示:在这里插入图片描述
    读到这里,可能就有人有疑问了——既然顺序表是用数组来实现的,那么两者的区别是什么? 在讲这个问题之前,我先给大家看个图在这里插入图片描述
    我来解释一下这个图的意思:炒西兰花和绿野仙踪的本质都是西兰花,但是,对西兰花进行装饰和好看的摆盘,就成了绿野仙踪(价格也漂亮!),就是对西兰花进行了漂亮的封装一个普通的数组可以进行数据的存储和数据的访问,功能很少。但是,经过对数组进行封装,我们在它原来的功能基础上增加了删除数据,增加数据和自动增加数组容量,就摇身一变成了顺序表。
  • 结构顺序表的基本功能要对数据进行存储,所以我们自然少不了数组形式的存储。我们还要知道这个顺序表的有效数据个数(存储了多少个数据)对于动态顺序表,我们还要知道顺序表的容量。所以,针对于以上的特征我们要用到结构体。结构体知识忘的同学可以回顾:点击:《结构体》。
  • 分类分为静态顺序表动态顺序表
    • 静态顺序表:以定长数组为原理进行存储。 结构如图所示:在这里插入图片描述
      静态顺序表有个致命的缺点——容量大小是固定的。我们静态顺序表里面的数组大小是固定的,当我们要存储的数据量较多时,就会出现空间不够用,当我们存储的数据量很少时,就会出现空间的大量浪费。为了避免空间的不足或浪费,我们每次都要调整数组的容量,这就很不方便,代码执行效率太低了。所以,我们一般不用静态顺序表。我们最常用的是动态顺序表——因为它能自动改变数组的容量
    • 动态顺序表:用动态内存函数realloc进行空间的申请。结构如图所示:在这里插入图片描述
      动态顺序表相对于静态顺序表,里面多了一些东西。因为我们是在原来空间基础上扩容的,所以要用realloc,又因为我们要用动态内存函数realloc进行空间的开辟,所以我们要用SLDatatype * arr;来接受malloc因为存储什么类型的数据,我们不知道,所以要用typedef宏定义,我们根据数据类型直接改宏定义,就能改变全局数据类型。capacity就是用来确定我们要开辟的空间大小。我们后面展示的代码都是以动态数组为根据的。
  • 动态顺序表的实现:我们要建立三个文件来实现动态顺序表
1. 建个Sqlist.h文件:用于函数和结构体的声明。
2. 建个Sqlist.c文件:用于实现各个功能函数。
3. 建个 test.c 文件:用来测试顺序表的功能。

进行图片展示:在这里插入图片描述
接下来,我直接给大家展示顺序表的各个功能代码的实现。

  • Sqlist.h
#pragma once     	  	//头文件的定义格式
#include <stdio.h>   	//我们直接把需要的头文件都定义在<Sqlist.h>,
#include <stdlib.h>		//我们就不用在<test.c>写这些头文件了。
#include <assert.h>
typedef int SLDatatype;  //宏定义,便于我们后续修改数据类型。
typedef struct Sqlist
{
	SLDatatype* arr;   //接收malloc返回的空间地址
	int size;      //有效数据个数
	int capacity; 	 //顺序表的容量
}SL;

void SqlistNit(SL* pp); //顺序表初始化
void my_printf(SL* p);  //打印函数
void Sqlistcheck(SL* p);  //检查空间够不够

void Sqlistpopback(SL* p); //尾部删数据
void Sqlistpushback(SL* ps, SLDatatype x); //数据尾插

void SqlistpopFront(SL* ps); //数据头删
void SqlistpushFront(SL* ps, SLDatatype x); //数据头插

void SqlistpushSy(SL* p, int da, SLDatatype x);//任意位置插入数据
  • Sqlist.c
#define  _CRT_SECURE_NO_WARNINGS	1
#include "Sqlist.h"  //引用<Sqlist.h>头文件
void Sqlistcheck(SL*p)   //检查空间够不够
{
	assert(p);   //传递的指针不能为空
	if (p->size == p->capacity)
	{
		int newcapacity = p->capacity == 0 ? 4 : p->capacity * 2; //当容量不够时,就自动扩容原来的2倍。
		p->capacity = newcapacity;
		SLDatatype* temp = (SLDatatype*)realloc(p->arr, newcapacity * 2 * sizeof(SLDatatype));  //malloc开辟空间,用temp接收,要注意类型的转换。
		if (temp != NULL)
			p->arr = temp;  //判断空间开辟是否成功,开辟成功就赋值
		else
			return 1;  //开辟失败就直接返回
	}
}
void Sqlistpushback(SL*ps,SLDatatype x)  //数据尾插
{
	assert(ps); //判断传递的是否为空指针
	Sqlistcheck(ps); //检查空间够不够
	ps->arr[ps->size++] = x; 
}
void SqlistpushFront(SL*ps,SLDatatype x)  //数据头插
{
	assert(ps);  //判断传递的是否为空指针
	Sqlistcheck(ps); //检查空间够不够
	for (int i = ps->size;i>0; i--)
	{
		ps->arr[i] = ps->arr[i-1];
	}
	ps->arr[0] = x;
	ps->size++;  //因为我们插入了数据,所以有效数据个数就要增加。
}
void SqlistpopFront(SL*ps)  //数据头删
{
	assert(ps&&ps->size);  //有效数据个数不能为空,要不然就不用删了
	for (int i = 0; i + 1 < ps->size; i++)
	{
		ps->arr[i] = ps->arr[i+1];
	}
	ps->size--;  //因为删除了数据,所以有效数据个数就减少
}
void SqlistNit(SL*pp)    //初始化
{
	pp->arr = NULL; //防止野指针的发生
	pp->size = pp->capacity = 0;
}
void my_printf(SL* p)  //打印数据
{
	int i = 0;
	for (i = 0; i < p->size; i++)
	{
		printf("%d ",p->arr[i]);
	}
	printf("\n");
}
void Sqlistpopback(SL* p)  //尾部删数据
{
	assert(p);   	//判断传递的是否为空指针
	--p->size; 		 //因为删除了数据,所以有效数据个数就减少
}
void SqlistpushSy(SL* p,int da,SLDatatype x) //任意位置插入数据
{
	assert(p);  //判断传递的是否为空指针
	Sqlistcheck(p);  //检查空间是否足够
	for (int i = p->size;i-1>=da; i--)
	{
		p->arr[i] = p->arr[i-1];
	}
	p->arr[da] = x;
	p ->size++;   //插入数据,有效数据个数就增加
}

我们对于容量的扩容,一般采用2倍扩容。前提是整数倍,因为内存空间没有小数这一说,当小于2倍时,扩容量较小,数据可能存放不下,当大于2倍时,扩容量较大,空间浪费。所以,我们一般采用2倍扩容,刚好在起始位置上增加1倍空间。

  • test.c :用来测试顺序表的各个功能函数。
#define  _CRT_SECURE_NO_WARNINGS	1
#include "Sqlist.h"
// 可以根据自己的需求来自行测试顺序表的各个函数的功能
void test()
{
	SL s1;
	SqlistNit(&s1);   		//给大家举个顺序表插入数据的例子
	Sqlistpushback(&s1,2);
	Sqlistpushback(&s1,2);
	Sqlistpushback(&s1,2);
	Sqlistpushback(&s1,2);
	my_printf(&s1);
}
int main()
{
	test();
	return 0;
}

结果运行图:在这里插入图片描述

  • 总结因为动态顺序表的空间和数组一样,所以我们就可以可以通过++- -来对空间进行访问。我们要注意传递的指针是否为空指针,当删除或插入数据时,要注意有效数据个数的变化。
  • 对于动态内存开辟不懂得同学可以查看:点击:《动态内存管理》。
  • 对于指针(一级和二级指针)不懂得同学可以查看:点击:《深入理解指针1》.

顺序表问题与思考

  • 中间/头部的插入删除,时间复杂度为O(n).
  • 增容需要申请新空间,拷贝数据,释放就空间,会有不小的消耗,执行效率不是很好。
  • 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再插入5个数据后,那么就会有95个空间浪费了。思考一下:我们该怎样解决以上的问题呢?预告:下期《链表》就会解决的

彩蛋时刻!!!

给大家听个欢快的曲子,给大家放松放松一下:机器人之梦:《September》在这里插入图片描述
每章一句人生漫长,祝我们都可爱的不像话!感谢你能看到这里,点赞+关注+收藏+转发是对我最大的鼓励,咱们下期见!!!

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

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

相关文章

ICT产业新征程:深度融合与高质量发展

在信息时代的浪潮中&#xff0c;每一场关于技术革新与产业融合的盛会都闪耀着智慧的光芒&#xff0c;引领着未来的方向。9月25日&#xff0c;北京国家会议中心内&#xff0c;一场聚焦全球信息通信业的顶级盛事——第32届“国际信息通信展”&#xff08;PT展&#xff09;隆重拉开…

C++新手入门指南:从基础概念到实践之路

C 继承了 C 语言的高效性和灵活性&#xff0c;同时新增了面向对象编程的特点。这使得 C 既可以进行底层系统编程&#xff0c;又能进行面向对象的软件设计。在面向对象编程方面&#xff0c;C 支持封装、继承和多态三大特性。 &#x1f4af;C 初印象 语言的发展就像是练功打怪…

【Docker】Docker基本操作

目录 一、了解云计算背景 1.1 云计算的三种服务模式 1.2 虚拟机的两种架构 二、Docker 概述 2.1 Docker简述 2.2 Docker 特点 2.3 Docker与虚拟机的区别 2.4 容器技术有哪些 2.4.1 namespace的六项隔离 2.5 Docker核心概念 2.5.1 镜像 2.5.2 容器 2.5.3 仓库 三、…

吴恩达深度学习笔记(6)

正交化 为了提高算法准确率&#xff0c;我们想到的方法 收集更多的训练数据增强样本多样性使用梯度下降将算法使算法训练时间更长换一种优化算法更复杂或者更简单的神经网络利用dropout 或者L2正则化改变网络框架更换激活函数改变隐藏单元个数 为了使有监督机制的学习系统良…

笔试强训10.17

//法一&#xff1a;中点扩散 //法二&#xff1a;动态规划 //法三&#xff1a;hash二分 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N1e610; const int base131; ull hr[2*N],hl[2*N],p[2*N];//超过ull自动取余 char s[N*2];…

如何优化批处理策略,最大限度地“压榨”GPU性能

新手数据科学家和机器学习工程师常常会问一个关键问题&#xff1a;如何判断他们的深度学习训练过程是否在正常运行&#xff1f;在本文中&#xff0c;我们将学习如何诊断和优化深度学习的性能问题&#xff0c;不论是在单台机器还是多台机器上进行训练。通过这些方法&#xff0c;…

uniapp onPageScroll

子组件有onPageScroll, 首页也要引入onPageScroll, eg: 主页面 sell/detail/index 《子组件》 <script setup> 引入onPageScroll </script> 组件&#xff1a; 引入onPageScroll 别人的比较

阿里 C++面试,算法题没做出来,,,

我本人是非科班学 C 后端和嵌入式的。在我面试的过程中&#xff0c;竟然得到了阿里​ C 研发工程师的面试机会。因为&#xff0c;阿里主要是用 Java 比较多&#xff0c;C 的岗位比较少​&#xff0c;所以感觉这个机会还是挺难得的。 阿里 C 研发工程师面试考了我一道类似于快速…

五个必备的高清无水印视频素材库推荐

做抖音、短视频创作的朋友都知道&#xff0c;优质的素材往往决定了作品能否获得更多关注。如果你还不知道在哪里下载高清无水印的视频素材&#xff0c;不用担心&#xff01;今天为你推荐5个高品质的视频素材库&#xff0c;助你轻松创作出爆款视频。 蛙学网 是国内领先的视频素材…

Windows 11 24H2版本有哪些新功能_Windows 11 24H2十四大新功能介绍

距离上次发布的23H2版本已经过去了一年时间&#xff0c;现在&#xff0c;Win 11的24H2版本终于等到了&#xff0c;微软已经全面公开发布Win11 24H2版本&#xff0c;版本号为26100.1742&#xff0c;此次官宣的版本包括了消费者版、商业版、LTSC 2024版等&#xff0c;各种语言版本…

选择合适的SSL证书

随着我们在线业务的增长&#xff0c;确保网站安全变得越来越重要。对于许多人来说&#xff0c;保护网站安全的想法似乎令人望而生畏&#xff0c;尤其是在有各种SSL证书可用的情况下。您可能想知道哪一个最适合您的业务需求或如何浏览这些选项。 除了SSL证书之外&#xff0c;使…

IIC协议解析

文章目录 1 IIC理解1.1 IIC简述1.2 IIC协议优缺点1.3 传输速度 2 IIC数据格式3 数据时序3.1 写时序3.2 读时序 参考链接 1 IIC理解 1.1 IIC简述 IIC全称Inter Integrated Circuit&#xff0c;即集成电路总线。是由Philips半导体公司于八十年代初设计出的一种两线式串行总线协议…

雷达手势识别技术

1、IR-UWB 手势识别方案 该任务可以分为数据采集&#xff0c;雷达数据处理&#xff0c;识别分类三个部分。 1.1 UWB Radar 数据处理 首先采集慢时间快时间维数据&#xff1a; 然后仍然是Clutter removal filter&#xff1a; 之后正则化转化为灰度图像&#xff1a; 使用matlab f…

springboot+大数据+基于大数据的电脑硬件推荐系统【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

虚幻闪烁灯光材质

创建一个材质 材质域改成光照函数 , Time让材质动起来 参数B用来控制速度 , Sine 让灯光闪烁 , Frac 增加了闪烁细节 把材质放到灯光材质上 效果还是挺不错的! 可以用于一些恐怖游戏~

Redis和Jedis的区别

目录 含义与用途 Jedis案例 总结 含义与用途 Redis&#xff1a; 概念&#xff1a;Redis是一个基于内存的键值存储数据库&#xff0c;支持丰富的数据结构。比如&#xff1a;字符串功能&#xff1a;除了基础的数据存储&#xff0c;Redis还提供了丰富的高级功能。如持久化&…

Python第七八次作业

1.输入一个大于0的正整数n&#xff0c;如果n 1 ,则返回1&#xff0c; 如果n是偶数&#xff0c;则返回 n // 2 &#xff0c;如果n是奇数&#xff0c;则返回 3n 1&#xff0c;将所有的返回值存放到一个列表中&#xff0c;注意&#xff1a;n是第一个元素&#xff0c;其他的元素根…

entity,pojo,vo,dto 详解

在Java项目中&#xff0c;包名通常用于组织代码&#xff0c;使其更加清晰和易于维护。entity、pojo、vo和dto是常见的包名&#xff0c;它们各自有不同的含义和用途。下面将详细解释这些包名的含义&#xff0c;并提供一个示例&#xff0c;帮助你更好地理解它们在项目中的应用。 …

DAPLINK 之 RTT 输出日志

文章目录 前言1 安装 SEGGER RTT2 OpenOCD 下的 rtt2.1 调试环境2.2 输出日志 3 关于日志中的文件名参考 前言 1&#xff09;RTT&#xff08;Real Time Transfer&#xff0c;实时传输&#xff09;&#xff1a;SEGGER 的 Real Time Transfer (RTT) 是一种经过验证的技术&#x…

mysql查看和修改默认配置

1.查看最大连接数 SELECT max_connections; 或者 SHOW VARIABLES LIKE max_connections;2.查看当前连接的客户端 SHOW PROCESSLIST;2.临时设置最大连接数 SET GLOBAL max_connections 500;3.临时设置连接客户端交互超时时间 SET GLOBAL interactive_timeout 1800;4.永久生…