前言

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

顺便解答下为什么大部分编程语言的的数组是从 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 支持负下标。

最新文章

  1. BootStrap_04之jQuery插件(导航、轮播)、以及Less
  2. 微信接口-获取用户openid基本信息
  3. C的数值取反操作
  4. AFN框架内部结构
  5. Android度量单位说明(DIP,DP,PX,SP) (转帖)
  6. 比较二个文件的最后修改时间FileListener
  7. xcode 左边导航栏中,类文件后面的标记“A”,&amp;quot;M&amp;quot;,&amp;quot;?&amp;quot;……等符号的含义???
  8. spring 自动化构建项目
  9. adb devices找不到设备解决办法
  10. SVN简介与安装
  11. Money King【题解】
  12. shiro执行原理
  13. 启动一个SpringBoot的maven项目
  14. Linux 单引号和双引号的区别
  15. poi 实战代码---导出Excel(根据模板导出)
  16. 【转载】Maven中的BOM概念
  17. 5月29,48h,Geekathon,创业极客的梦想起点
  18. dubbo的spi机制
  19. angular.element()的用法
  20. hibernate注解note

热门文章

  1. xml字符串转成数组(php)
  2. 限制只有VIP会员才能下载Ecshop文章页的附件
  3. 51nod1667-概率好题【容斥,组合数学】
  4. AT4995-[AGC034E] Complete Compress【树形dp】
  5. AT4502-[AGC029C]Lexicographic constraints【二分,栈】
  6. 三、mybatis多表关联查询和分布查询
  7. 从一个舒服的姿势插入 HttpClient 拦截器技能点
  8. 生成base64图片验证码
  9. 每日总结:Java课堂测试第三阶段第二次优化 (四则运算) (2021.9.22)
  10. Azure Tips 第一期: Azure 中的安全监视工具,数据存储, 动态数据屏蔽以及资源部署