数组是一种线性数据结构,它用连续的内训空间,来存储一组局具备相同类型的数据java
第一线性表:顾名思义,线性表就是数据排成像一条线同样的结构,每一个线性上的数据最多只有先后两个方向,其实除了数组、链表、队列、栈等也是线性结构程序员
而与它相对立的概念是非线性表,好比二叉树、堆、图等,之因此叫非线性,是由于,在非线性表中、数据之间并非简单的先后关系算法
第二个是连续的内存空间和相同类型的数据,正是由于这两个限制,它才有了一个堪称“杀手锏”的特性“随机访问”。但有利有弊,这两个限制数组
也让数组的不少操做变得很是低效,好比要在数组中删除、插入一个数据,为了保证连续性,就须要作大量的数据搬移工做。性能优化
说到数据的访问,那你知道数组是如何实现根据下标随机访问数组元素的吗?bash
咱们知道,计算机会给每一个内存单元分配一个地址,计算机经过地址来访问内训中的数据,但计算机须要随机访问数组中的某个元素时
它会首先经过下面的寻址公式,计算出该元素存储的内存地址:网络
a[i]_address = base_address + i * data_type_size
data_type_size表示数组中每一个元素的大小,咱们举的这个例子里,数组中存储的是int类型数据,因此data_type_size就为4个字节。数据结构
不少人回答说:链表适合插入、删除、时间复杂度O(1);数组适合查找,查找时间复杂度为 O(1)”框架
实际上这种表述是不许确的,数组是适合查找操做,可是查找的时间复杂度并不为O(1),即使是排好序的数组,你用二分查找,时间复杂度也是O(logn)。性能
因此,正确的表述应该是,数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)。
插入:最好O(1) 最坏O(n) 平均O(n)
删除:最好O(1) 最坏O(n) 平均O(n)
数组若无序,插入新的元素时,能够将第K个位置元素移动到数组末尾,把新的元素,插入到第k个位置,此处复杂度为O(1)
实际上,在某些场景下,咱们并不必定非得追求数组中数据的连续性,若是咱们将屡次删除操做集中在一块儿执行,删除的效率是否是是提升不少的呢?
屡次删除集中在一块儿,提升删除效率
记录下已经被删除的数据,每次的删除操做并非搬移数据,只是记录数据已经被删除,当数组没有更多的存储空间时,
再触发一次真正的删除操做。即JVM标记清除垃圾回收算法。
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; }
用C语言循环越界访问的例子说明访问越界的bug。此例在《C陷阱与缺陷》出现过,很惭愧,看过可是如今也只有一丢丢印象。翻了下书,替做者加上一句话:
若是用来编译这段程序的编译器按照内存地址递减的方式给变量分配内存,那么内存中的i将会被置为0,则为死循环永远出不去。
相比于数字,java中的ArrayList封装了数组的不少操做,并支持动态扩容。一旦超过存储容量,扩容时比较耗内存,由于涉及到内存申请和数据搬移。
因此、若是事先能肯定须要存储的 数据大小,最好在建立ArrayList 的时候事先指定数据大小
好比咱们要从数据中去吃醋10000条数据放入ArrayList。咱们看下面几行代码,你会发现,相比之下,
实现指定数据大小能够省掉不少次内存申请和数据搬移操做
ArrayList<User> users = new ArrayList(10000); for (int i = 0; i < 10000; ++i) { users.add(xxx); }
1) Java ArrayList 的使用涉及装箱拆箱,有必定的性能损耗,若是特别管柱性能,能够考虑数组
2) 若数据大小事先已知,而且涉及的数据操做很是简单,可使用数组
3) 表示多维数组时,数组每每更加直观。
4) 业务开发容器便可,底层开发,如网络框架,性能优化。选择数组。
1) 从偏移角度理解a[0] 0为偏移量,若是从1计数,会多出K-1。增长cpu负担。为何循环要写成
for(int i = 0;i<3;i++)
而不是
for(int i = 0 ;i<=2;i++)
第一个直接就能够算出3-0 = 3 有三个数据,然后者 2-0+1个数据,多出1个加法运算,很恼火。
一、C语言设计者用哪一个0开始计数数组下表,以后java、JavaScript 等高级语言都效仿了 C 语言
二、或者说,为了在必定程度上减小 C 语言程序员学习 Java 的学习成本,所以继续沿用了0开始计数的 习惯
三、实际上,不少语言中数组并非从0开始计数的,好比 Matlab。甚至还有一些语言支持负数下标,好比Python
前面我基于数组的原理引出 JVM 的标记清除垃圾回收算法的核心理念我不知道你是否使用 Java 语言,理解JVM
若是你熟悉,能够在评论区回顾下你理解的标记清除垃圾回收算法。
前面咱们讲到一维数组的内存寻址公式,那你能够思考一下类比一下,二维数组的内存寻址公式是怎样的呢?