数据结构与算法(一)-常用容器的了解
需要先学习一些Java的基础,另外此篇文章是为了之后的算法做铺垫
数据结构与算法系列参看:
1.数据结构与算法-黑马程序员(B站)
2.数据结构 - 清华大学(学堂在线)
3.https://www.cnblogs.com/l199616j/p/10742603.html#_label1_5
4.数据结构与抽象 Java语言描述(第四版)(黑皮书)
5.数据结构(Java语言描述) - 丁海军
什么是数据结构和算法:
数据结构包括数据对象集以及他们在计算机中的组织方式,即它们的逻辑结构和物理存储结构,一般我们可以认为数据结构指的是一组数据的存储结构。
算法就是操作数据的方法,即如何操作数据效率更高,更节省资源.
1.数组
1.1 概述
数组是一种线性表结构,它用一组连续的内存空间,来存储具有相同类型的数据。
在Java中数组的创建方式有3种:
//1.直接创建并且赋值
int[] a = {
1, 3, -1, -3, 5, 3, 6, 7};
//2.创建指定的大小而不赋值
int[] b = new int[10];
//3.创建一个引用 在后续可以指定大小 而不是直接使用方式1的格式进行赋值
int[] c;
获取数组的长度
int[] arr = new int[10];
int size = arr.length;//size == 10
1.2 逻辑结构和物理结构
逻辑结构指的是我们可以用什么方式来描述数组元素(我们把数组a的逻辑结构表示为a1,a2,a3,…,an)。
物理结构指的是在计算机中数组的存储方式,数组使用一块连续的物理空间
1.2.1 数组元素的访问
拿数组int[] a = new int[10]
为例,给计算机分匹配一块连续的内存空间,100-139,内存起始地址为baseAddress=100:
寻址公式:
//其中的dataTyperSize为数据类型大小
a[i] = baseAddress + i * dataTyperSize
即使是二维数组,它的存储地址仍然的连续的:
1.3 数组的特点
- 高效随机的访问:数据在内存上连续,通过寻址公式快速找到;
- 低效的插入和删除:在连续的数据中插入和删除就需要移动大量的数据元素保证数据内存地址连续。
- 插入:如果只需要将某个数据插入到第k个位置,可以直接将k位置的旧数据搬移到数组的最后,新数据插入到k位,这就是快排思想;
- 删除:实际上并不一定要追求数组中数据的连续性,可以将多次删除操作在一起执行,减少移动次数。具体是在每次的删除操作不是真正的删除数据,而是记录下已经删除的数据,当数组没有更多空间存储数据时,再触发执行真正的删除操作,这样也极大的减少了删除造成导致的数据搬移。
其实上面描述的数组的删除策略就是JVM标记清理垃圾回收算法的核心思想。
2.链表
2.1 概述
2.2 链表类型
1.单链表
2.循环链表
3.双向链表
4.双向循环链表
2.3 链表数组的性能比较
从结构上来分析:
- 数组在内存上是占用一片连续的内存空间,所以随机访问效率会非常好,查询效率很高,必须是一段连续的内存空间;
- 链表存储结构是采用离散的内存空间,有指针指向下一个数据,所以在删除的时候无序大量移动数据元素。
所以就是数组的优势是查询速度非常快、增删改慢,链表的优势是增删改快、查询慢。且在数据长度确定的情况下链表比数组更消耗内存。
同时,在分析Map、List等的使用场景时,先弄明白它的底层实现是依赖数组还是链表的,这些就能明确什么情况下使用什么容器进行数据操作。
单链表反转题:
https://leetcode-cn.com/problems/reverse-linked-list/
实现链表的容器有很多,可以去看一下LinkedList的源码。
3.栈
3.1 概述
栈有一个典型的特点:先进后出,后进先出;后进先出(Last In First Out,LIFO)
栈是一种操作受限的线性表,只允许在栈的一端进行数据的插入和删除,这种操作称为入栈和出栈(压栈/弹栈)。当某个数据集合如果只涉及到在其一端操作数据的时候,并且满足先进后出的特性时,就可以使用到栈。
3.2 栈的实现
使用数组实现的栈称为顺序栈,使用链表实现的栈称为链式栈。手写实现栈:
顺序栈:
public class ArrayStack