数组
百度百科解释:
所谓数组,是有序的元素序列。若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。 这些无序排列的同类数据元素的集合称为数组。数组是用于储存多个相同类型数据的集合。
自我粗解:
- 在内存中,数组是一块连续的区域(逻辑上相邻的元素在物理存储位置上也相邻)
- 数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间(数组空间利用率低)
- 在数组起始位置处,插入数据和删除数据效率低(平均需要移动n/2个元素、时间复杂度为O(N))
- .随机访问效率很高,时间复杂度可以达到O(1)
- 数组开辟的空间,在不够使用的时候需要扩容,需要把旧数组中的所有元素向新数组中搬移
- 数组的空间是从栈分配的
链表
百度百科解释:
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)。
简单而言:
- 在内存中,元素的空间是分散的,不需要连续
- 链表中的元素都会两个属性,一个是元素的值(数据域),另一个是指针,此指针标记了下一个元素的地址(可通过此地址找到下一元素位置)
- 查找数据时效率低,时间复杂度为O(N)(空间分散,需遍历)
- 空间不需要提前指定大小,是动态申请的,根据需求动态的申请和删除内存空间,扩展方便,故空间的利用率较高
- 任意位置插入元素和删除元素效率较高,时间复杂度为O(1)
- 链表的空间是从堆中分配的
方法时间复杂度
操作 | 数组 | 链表 |
---|---|---|
读取 | O(1) | O(n) |
插入 | O(n) | O(1) |
删除 | O(n) | O(1) |
#代码验证(插入方法)
//数组插入所花时间检验
// i=100000 --65058ms
// i=10000 --6704ms
// i=1000 --717ms
public class Array {
static String[] array1 = new String[10];
String[] array2 = new String[1000000];
private static int size = 0;
public static void main(String[] agrs) {
Array a = new Array();
for (int i = 0; i < 10; i++) {
array1[i] = "jio" + i;
size++;
}
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
a.add("juu" + i);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
public void add(String str) {
int i;
for (i = 0; i < array1.length; i++) {
array2[i] = array1[i];
}
size++;
array2[size + 1] = str;
array1 = array2;
}
}
//链表插入所花时间检验
// 100000 --2ms
// 10000 --1ms
// 1000 --1ms
public class List {
Node head = null; // 头节点
class Node {
Node next = null;// 节点的引用,指向下一个节点
int data;// 节点的对象,即内容
public Node(int data) {
this.data = data;
}
}
public void addNode(int d) {
// 实例化一个节点
Node newNode = new Node(d);
if (head == null) {
head = newNode;
return;
}
Node tmp = head;
while (tmp.next != null) {
tmp = tmp.next;
}
tmp.next = newNode;
}
public static void main(String[] args) {
List list = new List();
long start = System.currentTimeMillis();
list.addNode(100000);
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
其他
数组实现队列与栈:
public class Stack {
private Object[] value;
private int top = -1;
private int size;
public Stack(int size) {
value = new Object[size];
this.size = size;
}
public boolean isEmpty() {
return top == 0;
}
public void push(Object val) {
if (top == size) {
throw new StackOverflowError();
}
value[++top] = val;
}
public Object pop() {
if (top < 0) {
throw new EmptyStackException();
}
Object obj = value[top];
top--;
return obj;
}
}
public class Queue {
private Object[] queue;
private int length;
private int head = 0;
private int tail = 0;
public Queue(int len) {
this.length = len;
queue = new Object[len];
}
public void enQueue(Object obj) {
if (tail == length) {
tail = 0;
}
queue[tail++] = obj;
}
public Object deQueue() {
if (queue[head] == null) {
return null;
}
Object temp = queue[head];
if (head == length) {
head = 0;
} else {
head++;
}
return temp;
}
}
链表实现队列和栈:https://blog.csdn.net/yhflyl/article/details/86541046
参考博客
1.数组和链表的区别 https://blog.csdn.net/dangzhangjing97/article/details/81699050
2.Java实现链表的各种方法 https://blog.csdn.net/jianyuerensheng/article/details/51200274
3.自己动手实现ArrayList以及LinkList https://github.com/byhieg/JavaTutorial/tree/master/src/main/java/cn/byhieg/collectiontutorial/listtutorial#
4.Java基础——Queue、Deque、ArrayDeque源码分析 https://blog.csdn.net/qq_30379689/article/details/80558771
5.思维导图 https://blog.csdn.net/aitaozi11/article/details/79652943