【追求卓越01】数据结构--数组

引导

        这一章节开始,正式进入数据结构与算法的学习过程中。由简到难,先开始学习最基础的数据结构--数组。

        我相信对于数组,大家肯定是不陌生,因为数组在大多数的语言中都有,也是大家在编程中常常会接触到的。我不会说数组有多困难,但是它绝对不是像我们所想的那么简单而已。

        带着问题进入今天的课题:为什么数组的下表从0开始,而不是从1开始

什么是数组

        我们还是从专业的角度来介绍一下数组:数组是一种线性表数据结构。它用一组连续的内存空间,来储存一组相同类型的数据。其中有几个知识点是需要我们了解的。

第一点是线性结构的概念。线性结构具有以下几个特点:

  1. 有唯一的首元素
  2. 有唯一的尾元素
  3. 除了首元素,所有的元素都有唯一的前驱
  4. 除了尾元素,所有的元素都有唯一的后继
  5. 数据元素之间存在“一对一”的关系

只要不满足以上特点的,就是非线性表。

常见的线性结构有:栈,数组,队列,堆,链表

常见的非线性结构有:树,图

        第二点是连续的内存空间和相同类型的数据结构。这两点正是数据数组强大的主要原因--高效的访问操作(随机访问)。我们知道数组在查询操作中具有很高的效率。但是原因是什么呢?我们一起来分析一下。

        例: 我们定义一个int 类型的数组,长度为10。假设首地址是base_address是1000。,那么它在内存中的分布应该如下图:

        比如我现在要访问数组中第5个数据a[4] (数组下标从0开始)。操作系统就会从 base_address+4*sizeof(int) 地址进行取值。正是通过这个公式实现数组的随机访问

        其实在这里,我们就可以回答刚开始导入的问题了:为什么数组的下表从0开始,而不是从1开始?

原因有二:

  1. 我们知道数组的随机访问是通过base_address+i*sizeof(data_type_size)公式计算的。如果数组的下表从1开始,数据在内存中的分布是不会改变的。上面的例子就是:访问数组中第5个数据a5。操作系统就会从base_address+(i-1)*sizeof(data_type_size)这个地址进行取值。相对于上面的公式,多了一个减法操作。(这种常用操作,对于CPU而言,性能的提升可能是很大的)。但这并不是主要原因,因为也有语言中数组的下表不是从0开始。
  2. 历史原因,因为C语言作为最早出现的高级语言,它的数组下标就是从0开始的。后面java等其它高级语言在创建之初,就继承了这一特性。(大部分人都已习惯从0开始)

数组的增删查

        数组的最大优势就是高效的查询。但是这其中也存在一定的坑。比如:数组的查询复杂度是O(1)。这句话是正确的吗?

错误的,因为即使是有序的数组,采用二分法。查询的复杂度也应该是O(logn)。准确的说法应该是:数组根据下标查询的复杂度是O(1)

数组的增加和删除是比较低效的操作了。因为增加一个或者是删除一个你要保证内存数据的连续性。

数组的越界

        数组的越界总是会发生一些意想不到的问题。我们看分析一下该代码,看看是什么现象。

int main(int argc, char* argv[]){
    int i = 0;
    int arr[3] = {0};
    for(; i<=3; i++){
        arr[i] = 0;
        printf("hello world\n");
    }
    return 0;
}

        现象是无限的打印“hello world”。我相信代码的错误点,大家肯定是知道的————数组越界访问。但是为什么会造成无限打印呢?这需要了解linux 虚拟内存分布以及栈的概念了。

        我们首先要知道linux进程的虚拟内存为4G,并且不同的地址分配着不同的资源。可参考下图:

其中各个空间分布,我就不再赘述了。只介绍该题需要分析的栈。需要注意以下几点:

  1. 栈也是一个数据结构,它的特点是先进后出。
  2. 并且它是向下连续增长的
  3. 一个线程中,是共享一个栈的。(线程中的栈大小是有限制)

我们知道局部变量是分布在栈中的,根据上面的代码,我们可以开始分析。

  1. int i=0;//i变量入栈,假设地址为1000
  2. int arr[3]={0};//arr数组入栈,arr[0]地址为988,arr[1]地址为992,arr[2]地址为996。

        分析到这里,我们就知道了,当访问arr[3]时,计算机根据base_address+3*data_type_size公式,实际上访问的是i变量,将i设置为了0,导致重新循环开始。所以一直无限打印“hello world”。

总结

        该篇简单介绍了数组这个数据结构。分析了它为什么能够实现随机访问。以及数组越界可能会带来的一些问题。数组比较适合用来查询,但是删除和增加,就比较低效了。

        对于超级大的数组,每次删除都会搬移其它数据。如果删除操作比较频繁。那么就是比较低效的。为了减少搬移数据的次数,我们可以将删除的变量进行标记(已使用或未使用),当内存不足时,再进行释放。这样就减少了搬移次数,提高效率。其实这也是JVM标记清除垃圾算法的思想。

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

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

相关文章

01【SpringBoot快速入门、yml语法、自动配置、整合框架】

目录 一、SpringBoot简介 1.1 Spring优缺点 1.1.1 Spring的优点 1.1.2 Spring的缺点 1.2 SpringBoot的概述 1.2.1 SpringBoot概述 1.2.2 SpringBoot的核心功能 二、SpringBoot快速入门 2.1 创建Maven工程 2.2 添加起步依赖 2.3 编写Controller 2.4 编写SpringBoot引…

c语言——俄罗斯方块

一、游戏效果 俄罗斯方块 二. 游戏背景 俄罗斯方块是久负盛名的游戏&#xff0c;它也和贪吃蛇&#xff0c;扫雷等游戏位列经典游戏的⾏列。 《俄罗斯方块》&#xff08;Tetris&#xff0c;俄文&#xff1a;Тетрис&#xff09;是一款由俄罗斯人阿列克谢帕基特诺夫于1984…

GIT实践与常用命令---回退

实践场景 场景1 回退提交 在日常工作中&#xff0c;我们可能会和多个同事在同一个分支进行开发&#xff0c;有时候我们可能会出现一些错误提交&#xff0c;这些错误提交如果想撤销&#xff0c;可以有两种解决办法:回退( reset )、反做(revert) keywords&#xff1a;reset、rev…

Android Spannable 使用​注意事项

1、当前示例中间的 "评论"&#xff0c;使用SpannableStringBuilder实现&#xff0c;点击评论会有高亮效果加粗&#xff0c;但再点击其它Bar时无法恢复默认样式。 2、因为SpannableString或SpannableStringBuilder中的效果是叠加的&#xff0c;恢复默认样式需要先移除…

创作4周年

&#x1f64c;秋名山码民的主页 &#x1f602;oi退役选手&#xff0c;Java、大数据、单片机、IoT均有所涉猎&#xff0c;热爱技术&#xff0c;技术无罪 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; 获取源码&#xff0c;添加WX 目录 前言机…

【鸿蒙应用ArkTS开发系列】- 云开发入门实战二 实现城市多级联动Demo(上)

目录 概述 云数据库开发 一、创建云数据库的对象类型。 二、预置数据&#xff08;为对象类型添加数据条目&#xff09;。 三、部署云数据库 云函数实现业务逻辑 一、创建云函数 二、云函数目录讲解 三、创建resources目录 四、获取云端凭据 五、导出之前创建的元数据…

Windows + VS2022超详细点云库(PCL1.8.1)配置

本文在结合多位CSDN大佬的步骤&#xff0c;记录以下最全的点云配置过程&#xff0c;防止走弯路&#xff08;并在最后配上PCL环境配置成功的测试代码-彩色兔子&#xff09; 一、PCL介绍 PCL概述_pcl技术_一杯盐水的博客-CSDN博客 二、准备工作&#xff08;PCL版本的下载&…

2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年危险化学品生产单位安全生产管理人员证模拟考试题库及危险化学品生产单位安全生产管理人员理论考试试题是由安全生产模拟考试一点通提供&#xff0c;危险化学品生产单位安全生产管理人员证模拟考试题库是根据危…

DedeBIZ 管理系统 DedeV6 v6.2.6 社区版 免费授权版

DedeBIZ 系统&#xff1a;开源、安全、高效的 DedeV6 v6.2.6 社区版 DedeBIZ 系统是基于 PHP 7 版本开发的&#xff0c;具有强大的可扩展性&#xff0c;并且完全开放源代码。它采用现流行的 Go 语言设计开发&#xff0c;不仅拥有简单易用、灵活扩展的特性&#xff0c;还具备更…

Golang版本处理Skywalking Trace上报数据

Tips: 中间记录了解决问题的过程&#xff0c;如不感兴趣可直接跳至结尾 首先去es里查询skywalking trace的元数据 可以拿到一串base64加密后的data_binary(直接解密不能用&#xff0c;会有乱码&#xff0c;可参考https://github.com/apache/skywalking/issues/7423) 对data_b…

[点云分割] 条件欧氏聚类分割

介绍 条件欧氏聚类分割是一种基于欧氏距离和条件限制的点云分割方法。它通过计算点云中点与点之间的欧氏距离&#xff0c;并结合一定的条件限制来将点云分割成不同的区域或聚类。 在条件欧氏聚类分割中&#xff0c;通常会定义以下两个条件来判断两个点是否属于同一个聚类&…

php文件上传例子

目录结构&#xff1a; index.html代码&#xff1a; <!DOCTYPE html> <html><head><title>文件上传</title><meta charset"utf-8"></head><body><form action"./up.php" method"post" encty…

CentOS 7 使用pugixml 库

安装 pugixml Git下载地址&#xff1a;https://github.com/zeux/pugixml 步骤1&#xff1a;首先&#xff0c;你需要下载pugixml 的源代码。你可以从Github或者源代码官方网站下载。并上传至/usr/local/source_code/ 步骤2&#xff1a;下载完成后&#xff0c;需要将源代码解压…

摩尔定律,梅特卡夫定律,吉尔德定律

信息系统的三大定律(摩尔定律&#xff0c;梅特卡夫定律&#xff0c;吉尔德定律)有一个清晰的视角&#xff1a; 信息系统不是左边的生产消费系统&#xff0c;而是右边的交易系统&#xff0c;交易系统与生产消费典型的区别在于信息交易过程会产生新的信息&#xff0c;就像钱一样…

【JVM精讲与GC调优教程(概述)】

如何理解虚拟机(JVM)跨语言的平台 java虚拟机根本不关心运行在其内部的程序到底是使用何种编程语言编写的,他只关心“字节码”文件。 java不是最强大的语言,但是JVN是最强大的虚拟机。 不存在内存溢出? 内存泄露? JAVA = (C++)–; 垃圾回收机制为我们打理了很多繁琐的…

一键去水印免费网站快速无痕处理图片、视频水印

水印问题往往是一个大麻烦。即使我们只想将这些照片保留在我们的个人相册中以供怀旧&#xff0c;水印也可能像顽固的符号一样刺激我们的眼睛。为了解决这个问题&#xff0c;我们需要不断探索创新的解决方案&#xff0c;让我们深入研究一款强大的一键去水印免费网站“水印云”。…

MySQL慢查询

快捷查看指令 ctrlf 进行搜索会直接定位到需要的知识点和命令讲解&#xff08;如有不正确的地方欢迎各位小伙伴在评论区提意见&#xff0c;博主会及时修改&#xff09; MySQL慢查询 MySQL 慢查询是指查询语句执行速度过慢&#xff0c;影响系统整体性能和查询效率的情况。MySQL…

防止恶意攻击,服务器DDoS防御软件科普

作为一种恶意的攻击方式&#xff0c;DDoS攻击正以超出服务器承受能力的流量淹没网站&#xff0c;让网站变得不可用。近几年&#xff0c;这种攻击持续增多&#xff0c;由此优秀服务器DDoS防御软件的需求也随之增长。那么如何选择服务器DDoS防御软件&#xff0c;从根本上根除DDoS…

Cent OS 8.2 安装 自定义硬盘 固定IP VMware

时间&#xff1a;20231122 环境&#xff1a;win11 、VMware 16 pro、Cent OS 8.2 说明&#xff1a;自定义安装方法、自定义硬盘分区、固定IP且能联网 1、使用自定义的方式安装虚拟机 此处选择典型&#xff0c;则会自动安装系统&#xff0c;无法自定义硬件以及配置信息 选择…

缓存雪崩、击穿、穿透_解决方案

文章目录 缓存雪崩、击穿、穿透1.缓存雪崩造成缓存雪崩解决缓存雪崩 2. 缓存击穿造成缓存击穿解决缓存击穿 3.缓存穿透造成缓存穿透解决缓存穿透 缓存雪崩、击穿、穿透 一般用户数据存储于磁盘&#xff0c;读写速度慢。 使用redis作为缓存&#xff0c;相当于数据缓存在内存&a…