文章目录
数据结构
一、什么是数据结构
1、数据结构的起源
1968年,美国的高纳得教授开设了一门基本算法的课程,开设了数据结构的先河。
数据结构:研究数据之间关系和操作的科学,而不是计算方法。
数据结构 + 算法 = 程序, 沃思 -> 图灵奖
程序: 可执行的二进制指令
2、数据结构的基本概念
数据:所有能够输入到计算机中去描述事物的符号。
数据元素: 数据的基本单位也叫作节点\顶点\记录。
数据项:有独立含义的数据最小单位,也叫做域。
数据结构:数据元素和数据关系的集合。
算法: 数据结构所具备的功能,解决特定问题的方法。
二、逻辑结构和存储结构
逻辑结构
集合:数据元素同属于一个集合,但是元素之间没有任何的关系。
线性结构:数据元素之间存在一对一的关系。(表)
树型结构:数据元素之间存在一对多的关系。(倒悬树)
图型结构:数据元素之间存在多对多的关系。(地图)
存储(物理)结构
顺序结构:数据存储在连续的内存中,用数据元素的相对位置来表示。
链式结构:数据元素存储在彼此独立的内存空间中,每个独立的元素也叫做节点,每个数据元素中增加一个数据项用来存储其他元素的地址,用来表示元素之间的关系。
逻辑结构和物理结构的对应关系:
表:顺序、链式
树:顺序、链式
图:顺序+链式
每种逻辑结构采用什么物理结构存储并没有明确规定,通常根据实际难度程度以及空间\时间来要求。
三、数据结构和运算
创建、增、删、改、查、清除、插入、排序、遍历等等
实现:ArrayList、LinkedList
Collection( I ) + Map( I )
Collection( I ):
|- List(I) - 顺序结构
|- ArrayList( C ) - 数组
|- LinkedList( C ) - 链表
|- Vector( C ) - 数组
|- Set(I) - 散列结构 -> Map(I)
|- SortedSet( I )
|- TreeSet( C )
|- hashSet( C )
|- Queue(I) - 队列
|- Dueque(I)
|-LinkedList( C )
List集合 - 顺序结构
1.List集合的特点
a.List集合是顺序结构,所以是有序列表,可以是用index
b.List集合允许有重复值
c.List集合允许有null值
2.特有方法(带有index)
add(int index, E element)
addAll(int index, Collection<? extends E> c)
set(int index, E element)
subList(int fromIndex, int toIndex)
remove(int index)
get(int index)
3.实现类
顺序结构(ArrayList)
底层实现:数组
底层数据结构:数组
特点:
优点: 查询速度很快(因为有连续的下标,可以根据下标进行查询)
缺点:
a.插入/删除很慢的
b.顺序结构需要连续的物理空间,导致空间的使用率非常低
链表结构(LinkedList)
底层实现:Node节点 -> date(数据) + next(下一个节点的引用)
底层数据结构:链表
特点:
a.链表在内存中是固定顺序的,但是他的物理空间不连续
b.没有下标,只有头节点
c.所有的操作只能从头节点出发
d.头节点 head: 不存数据,只有next
分类:
单向链表
双向链表
循环链表
优缺点:
优点: 插入/删除操作快,不需要连续的物理空间,所以空间使用率高
缺点: 查询速度,因为只能从头节点或尾节点开始查询
顺序结构 + 链表结构 -> 线性结构(栈、队列)
特有的方法:(只要带有first/last)
addFirst(E e)
addLast(E e)
getFirst()
getLast()
removeFirst()
removeLast()
Vector( C )
底层实现:数组
和ArrayList一样
不一样的地方:Vector加了锁(synchronized),线程安全,效率低。
对于插入/删除:
单个操作而言 -> linkedList比较快
但是:先查询,找到要插入/删除的位置的前一个节点
查询 + 插入(删除)
因为没有下标,所以查询非常慢
ArrayList和Vector的区别
1.线程安全分析
2.扩容容量:
ArrayList扩容为原容量的1.5倍
Vector扩容为原容量的2倍
Queue(I) - 队列(线性结构)
特点:
a.先进先出
b.允许有重复值
常用方法:
offer() - 向队列尾部追加元素
peek() - 从队列头部获取元素,但是队列不变
poll() - 从队列头部获取元素,删除元素
子接口 - Dqueue(I) - 双端队列/栈
可以根据方法区分是双端队列还是栈
Dqueue中的栈实现:
push() - 压栈
pop() - 弹栈
Set集合 - 散列表 (没有顺序的集合,不是随机)
特点 :
a.无序且唯一
b.使用equals判断元素是否重复
c.Set的物理空间是不连续的
实现类
HashSet( C ):
特点:
a.存储位置不是真正的随机位置,根据HashCode方法计算(决定)最终位置
b.使用equals()判断元素是否重复
存储过程:
1、调用自身的hashCode()计算存储位置
2、判断该位置上是否存在元素
3、如果该位置上存在元素
则使用equals()判断是否相等
如果相等则不存入
如果不相等,则存放到链表末尾
二叉树
特点:
a.不允许有重复值
b.永远都是(左在前,右在后)
c.左节点 < 父节点 < 右节点
遍历方式:
先序遍历 - 中左右
后序遍历 - 左右中
中序遍历 - 左中右
实现类
TreeSet( C )
底层实现:二叉树
父接口 -> SortedSet( I )
特点:
用来排序,最常用的是中序遍历
TreeSet存储过程:
①.最开始的数据跟根节点比较 - compareTo进行比较
②.如果比根节点大,存储在右边
③.如果比根节点小,存储在左边
④.如果元素一样,则不存入
Comparable 自然排序 和 Comparator 自定义排序(指定比较器)
1)所有的自然排序,底层下都是实现了Comparable接口
2)自然排序 Comparable
重写了compareTo()
将obj 和 this 进行对比
数组: Arrays.sort()
List: Collections.sort()
Set: TreeSet()
Map: TreeMap()
3)比较器排序 Comparator
重写了compare()
比较 o1 和 o2
数组: Arrays.sort(new Comparator)
List: Collections.sort(new Comparator)
Set: TreeSet(new Comparator)
Map: TreeMap(new Comparator)
4)结论:
sort方法不指定比较器的时候,需要的元素必须是实现Comparable。
sort方法指定比较器,元素不需要实现Comparable。