前言

本笔记主要记录数组的一些基础特性及操作。

顺便解答下为什么大部分编程语言的的数组是从 0 开始的。

李柱明博客:https://www.cnblogs.com/lizhuming/p/15487306.html

线性结构与非线性结构

线性结构:

  • 线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。
  • 包括:数组、链表、队列和栈等。

非线性结构:

  • 在非线性表,数据之间不是简单的前后关系,通过下图对比线性结构和非线性结构
  • 包括:树、图等。

参考图:

数组

数组的两个限制

数组有两个限制:

  1. 数组为线性结构。
  2. 是连续的内存空间和相同类型的数据。

数组的随机访问特性

基于以上两个限制,使得数组具有随机访问的特性。

小笔记:

  • 计算机通过地址来访问内存中的数据。

  • 寻址通过以下公式寻址:

    a[i]_address = base_address + i * data_type_size;

而随机访问是只要知道数组对应的下标,我们就可以直接通过寻址公式知道该数据,不需要查找什么的。使得时间复杂度为 O(1)。

小笔记:

  • 数组和链表的区别:

    • 数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)。
    • 链表适合增删,时间复杂度为 O(1)。

数组的操作

数组的操作主要是增删。

插入操作

插入数据,若不是尾部且不能留空,则需要搬移部分数据。

分析:

  • 若插入尾部,则不需要搬移数据,插入操作的时间复杂度为 O(1)。

  • 若插入第 k 个位置中。其插入操作的时间复杂度为 O(n)。

    • 特定情况下,可以把原有第 k 个位置中的数据挪到最后。这样其插入操作的时间复杂度为 O(1)。

删除操作

删除数据,若不是尾部且不能留空,则需要搬移部分数据。

分析:

  • 若删除尾部,则不需要搬移数据,删除操作的时间复杂度为 O(1)。

  • 若删除第 k 个位置中。其删除操作的时间复杂度为 O(n)。

    • 特定情况下,若删除的位前面几个,则可以直接修改数组的起始位置即可。

数组越界

小笔记:一个由 C/C++ 编译的程序占用的内存分为以下几个部分:

  • 堆区(stack):

    • 生长开口方向向上。(底为低地址、小端
    • 一般由程序员分配释放, 若程序员不释放,程序结束时可能
      由 OS 回收 。
  • 栈区(heap):

    • 生长开口方向向下。(底为低地址、小端
    • 由编译器自动分配释放 ,存放函数的参数值,局部变量的值
      等。其操作方式类似于数据结构中的栈。
  • 全局区(静态区)(static):

    • 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
    • 程序结束后有系统释放
  • 文字常量区:

    • 常量字符串就是放在这里的。
    • 程序结束后由系统释放。
  • 程序代码区:

    • 存放函数体的二进制代码。

参考代码:

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\n 。就是因为内存溢出。
  • 整型变量 i 和整型数组 arr[3] 存储在栈空间中。
  • arr[3] 的存储位置就是 i 的存储位置。
  • for 循环的合法循环 i 最大为 3,刚好在 i=3 的那次循环把 i 重置为 0 了。

这种数组越界的错误容易导致逻辑混乱。程序跑飞。

容器

针对数组类型,很多语言都提供了容器类,比如 Java 中的 ArrayList、C++ STL 中的 vector。

容器把很多数组操作的细节封装起来,如插入、删除等,且支持扩容。

数组下标

为什么大多数编程语言中,数组要从 0 开始编号,而不是从 1 开始呢?

  • 寻址效率原因。
  • 历史原因。

寻址:

  • 正常寻址:

    a[k]_address = base_address + k * type_size;
  • 若数组下标起始为 1 的寻址:

    a[k]_address = base_address + (k-1)*type_size;

每次寻址多了一个减法指令。

历史:

  • C 语言设计者用 0 开始计数数组下标,之后的 Java、JavaScript 等高级语言都效仿了 C 语言。

小笔记:

  • python 支持负下标。

【数据结构&算法】05-线性表之数组的更多相关文章

  1. JavaScript 数据结构与算法之美 - 线性表(数组、栈、队列、链表)

    前言 基础知识就像是一座大楼的地基,它决定了我们的技术高度. 我们应该多掌握一些可移值的技术或者再过十几年应该都不会过时的技术,数据结构与算法就是其中之一. 栈.队列.链表.堆 是数据结构与算法中的基 ...

  2. [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习)

    [数据结构1.2-线性表] 动态数组ArrayList(.NET源码学习) 在C#中,存在常见的九种集合类型:动态数组ArrayList.列表List.排序列表SortedList.哈希表HashTa ...

  3. 数据结构C++版-线性表

    PS:资料来源慕课网视频. 一.什么是线性表 线性表是n个数据元素的有限序列. 分类: 二.补充知识点 1.栈和队列有出操作.入操作,对应线性表(数组)为插入元素和删除元素,而线性表中要获取指定元素值 ...

  4. 【算法与数据结构实战】线性表操作-实现A并B,结果放入A中

    //数据结构与算法基础题1:线性表操作,实现A并B,结果放入A中 #include "stdafx.h" #include <iostream> #include &l ...

  5. Java数据结构与算法(1):线性表

    线性表是一种简单的数据类型,它是具有相同类型的n个数据元素组成的有限序列.形如如A0,A1,...,An-1.大小为0的表为空表,称Ai后继Ai-1,并称Ai-1前驱Ai. printList打印出表 ...

  6. 【C#数据结构系列】线性表

    一:线性表 1.1:定义:零个或多个数据元素的有限序列 1.2: 线性表元素个数n定义为线性表的长度,n = 0称为空表,i 为数据元素ai在线性表中的位序. 1.3:满足线性表的条件:(1):有序, ...

  7. C++ 数据结构 1:线性表

    1 数据结构 1.1 数据结构中基本概念 数据:程序的操作对象,用于描述客观事物. 数据的特点: 可以输入到计算机 可以被计算机程序处理 数据是一个抽象的概念,将其进行分类后得到程序设计语言中的类型. ...

  8. C语言数据结构——第二章 线性表

    二.线性表 2.1-线性表简介 2.1.1-线性表的定义 线性表是由若干个相同特性的数据元素组成的有限序列.若该线性表不包含任何元素,则称为空表,此时长度为0,当线性表不为空时,表中的元素的个数就是线 ...

  9. JAVA中的数据结构——集合类(线性表:Vector、Stack、LinkedList、set接口;键值对:Hashtable、Map接口<HashMap类、TreeMap类>)

    Java的集合可以分为两种,第一种是以数组为代表的线性表,基类是Collection:第二种是以Hashtable为代表的键值对. ... 线性表,基类是Collection: 数组类: person ...

  10. PHP数据结构之二 线性表中的顺序表的PHP实现

    线性表 (一)基本特点:最基本.最简单.最常用的一种数据结构 在这种结构中: 1.存在一个唯一的被称为“第一个”的数据元素: 2.存在一个唯一的被称为“最后一个”的数据元素: 3.除第一个元素外,每个 ...

随机推荐

  1. Java基础系列(17)- 顺序结构

    顺序结构 JAVA的基本结构就是顺序结构,除非特别说明,否则就按照顺序一句一句执行 顺序结构是最简单的算法结构 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执行的处理步骤组成的 ...

  2. 配置阿里云maven

    在安装好Maven之后,默认的~/.m2目录下是没有maven仓库配置文件settings.xml的,默认使用的是官方的仓库,访问速度会非常慢,我们需要配置下国内的仓库. 创建~/.m2/settin ...

  3. Java学习之随堂笔记系列——day04

    今日内容1.break和continue关键字以及循环嵌套    1.1 break和continue的区别?        continue表示跳过当前循环,继续执行下一次循环break表示结束整个 ...

  4. linux中创建公私钥

    linux中创建公私钥要再~(root)目录下ssh-keygencd /root/.ssh/lsid_rsa 是私钥id_rsa.pub 是公钥把 authorized_keys删除掉,重新建aut ...

  5. 『GoLang』包

    可见性规则 在Go语言中,标识符必须以一个大写字母开头,这样才可以被外部包的代码所使用,这被称为导出.标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的.但是包名不管 ...

  6. 鸿蒙内核源码分析(文件系统篇) | 用图书管理说文件系统 | 百篇博客分析OpenHarmony源码 | v63.01

    百篇博客系列篇.本篇为: v63.xx 鸿蒙内核源码分析(文件系统篇) | 用图书管理说文件系统 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...

  7. YbtOJ#631-次短路径【左偏树,最短路】

    正题 题目链接:https://www.ybtoj.com.cn/contest/114/problem/1 题目大意 给出\(n\)个点\(m\)条边的一张无向图,对于每个点\(i\)求不经过\(i ...

  8. FFT&原根&NTT&MTT

    FFT bilibili 3b1b视频讲解 核心过程: 原根 Definition 若 \(a\) 模 \(m\) 的阶等于 \(\varphi(m)\),则称 \(a\) 为模 \(m\) 的一个原 ...

  9. 题解 「BZOJ4919 Lydsy1706月赛」大根堆

    题目传送门 题目大意 给出一个 \(n\) 个点的树,每个点有权值,从中选出一些点,使得满足大根堆的性质.(即一个点的祖先节点如果选了那么该点的祖先节点的权值一定需要大于该点权值) 问能选出来的大根堆 ...

  10. SPOJ2939 QTREE5(LCT维护子树信息)

    QWQ嘤嘤嘤 此题正规题解应该是边分治??或者是树剖(总之不是LCT) 但是我这里还是把它当成一个LCT题目来做 首先,这个题的重点还是在update上 因为有\(makeroot\)这个操作的存在, ...