1.数组(Array)
介绍
-
java中的数组是一种用连续内存空间存储相同数据类型数据的线性数据结构。数组可以容纳同一种类型的元素,可以是int类型的数值,string类型的字符串,也可以是java对象
-
从数据结构上说,数组的内存空间是连续的,是一种顺序存储结构,属于引用数据类型。
-
我们创建数组的时候系统就会为我们开辟固定数目的内存空间,如果内存不足,就会创建失败,例如创建数组的两种方式:
int[] a=new int[3]; int[] b=new int[]{1,2,3}
-
可以看到我们创建数组的时候已经指定了数组的大小,且不能动态更改数组的大小,是因为创建时候已经分配了连续的固定内存空间,每个元素占用两个字节,这样我们就可以通过连续的内存,去访问数组的元素
数组的扩容
-
java中的原生的数组在初始化时就已经指定了数组的大小的,而当我们插入的数据超过数组的size后数组会扩容
-
系统会分配一个新的内存空间,这个新内存空间的大小是原本数组的1.5呗,然后将原数组的值复制到新的数组内存空间中,这就是数组的扩容
为什么下标从0开始,而不是1
-
从1开始的话,CPU每一次去根据寻址算法去寻址时都要进行一次减法命令,性能相对较低
查找的时间复杂度
-
随机查找,O(1)。直接根据下标查找
-
固定的一个元素(未排序),复杂度为O(n)
-
固定的一个元素(但排序),复杂度为O(log n)
插入删除
-
平均复杂度为O(n)
2.链表(LinkedList)
定义
-
链表是数据元素的线性集合,其每个元素都指向下个元素,元素存储上并不连续
-
链表的内存是动态分配的
分类
单向链表
-
每个元素只知道下一个元素的位置
双向链表
-
每个元素知道它的上一个元素和下一个元素的位置
循环链表
-
通常的链表结尾节点tail指向的都是null,而循环链表的tail指向的是头节点
性能
查询
-
时间复杂度为O(n)
插入删除
-
头节点:O(1)
-
结束位置:知道tail节点位置是O(1),不知道位置就是O(n)
-
中间位置:根据index查找时间+O(1)
3.队列(Queue)
定义
-
队列是以顺序的方式维护一组数据集合,在一端添加数据,从另一端移除数据。习惯来说,添加的一端称为尾,移除的一段称为头,就如同生活中排队买商品
-
也就是先进先出
队列的使用
在Java中Queue是接口,底层是通过链表实现的
常用方法
方法 | 说明 |
---|---|
boolean offer(E e) | 入列 |
E poll() | 出列 |
peek() | 获取队头元素 |
int size() | 获取队列中有效元素的个数 |
boolean isEmpty() | 检测队列是否为空 |
在Java中实现Queue时,必须实列化LinkedList对象
使用场景
-
队列常用于需要维护先进先出顺序的情况,如任务调度、广度优先搜索、消息传递系统等
4.栈(stack)
定义
-
栈是一种线性结构,只能在其一端添加数据和移除数据。
-
添加和移除的这一端称为栈顶,另一端不能操作数据称为栈底
压栈
-
像一个栈插入一个新的元素有称为进栈、入栈或者压栈,他是把新元素放到栈顶元素的前面,使之称为新的栈顶元素
出栈
-
从一个栈删除元素又称为出栈或者退栈,他是把栈顶元素删除掉,使之相邻的元素称为新的栈顶元素
栈的使用
栈的工作原理:后进先出,类似于叠盘子
常用方法
方法 | 功能 |
---|---|
Stack() | 构建一个空的栈 |
E push(E e) | 将e入栈,并返回e |
E pop() | 将栈顶元素出栈并返回 |
E peek() | 获取栈顶元素 |
int size() | 获取栈的有效元素个数 |
boolean empty() | 检测栈是否为空 |
使用场景
-
栈常用于需要维护后进先出顺序的情况,如递归函数的调用栈、表达式求值、撤销功能的实现等