数据结构
* 概念:程序当中组织和存储数据的一种方式,
* 算法:解决问题的一种办法,如何快速的查找数据/修改数据/删除数据/添加数据
* 常见的数据结构:8种
* 数组、链表、队列、栈(堆栈)、堆、树、图、哈希表
*
* 数组:
* Array:是有序的元素序列,数组在内存当中是一块连续的空间,并在此空间中存放我们的元素值
* 特点:
* 1. 查找元素快:因为每一块空间都有一个索引值,那么我们可以通过这个索引值快速的检索到对应的空间,从而取出空间里面存储的值
* 2. 增删元素慢:因为该空间在内存当中的存储的大小是固定的,所以当增删元素时需要创建一个新数组,遍历原来的数组
* 链表:
* LinkedList:内部由一系列的结点Node(把链表当中每个元素称之为一个结点),结点可以在程序的运行过程中动态生成,每个结点内部包含有两个部分:
* 一个是用来存储数据的数据域,另外一个是用来存储地址的指针(引用)域,存储的是下一个结点的地址
* 我们常说的链表结构有三种类型:单向链表、双向链表、循环链表
* 特点:
* 1. 结点之间使用指针(地址)进行连接
* 2. 查找元素慢:因为每次检索都需要从首节点开始,依次往后检索,直到找到对应的结点
* 3. 增删元素快:
* 单向链表:
* 每个结点内部包含有两个部分:一个是用来存储数据的数据域,另外一个是用来存储地址的指针(引用)域,存储的是下一个结点的地址
* head--->首节点--->第二个结点-->第三个结点--->末尾结点--->null
* 双向链表:
* private static class Node<E> {
* E item;
* Node<E> next;// 下一个地址
* Node<E> prev;// 上一个地址
*
* Node(Node<E> prev, E element, Node<E> next) {
* this.item = element;
* this.next = next;
* this.prev = prev;
* }
* }
* 每个结点内部包含三个部分:一个是用来存储数据的数据域,一个是存储下一个结点的地址,还有一个用来存储上一个结点的地址
* 优点:
* 1. 不需要初始化容器的大小
* 2. 可以添加任意的元素
* 3. 插入和删除元素时只需要更新引用即可。
* 缺点:
* 1. 占用的内存空间相对来说较大,因为含有大量的引用
* 2. 查找元素时需要遍历整个链表结构,耗时
*
* 队列:
* queue: 它允许从队列的一端存储元素,从队列另外一端取出元素
* 特点:
* 1. 先进先出
* 2. 入口和出口在队列的两端
* 栈:
* stack:堆栈,也它是一种受限的线性表结构,仅允许从栈的一端去添加和取出元素。
* 特点:
* 1. 入口和出口是在栈的一端
* 2. 存储和取出元素特点是先进后出,也就是先存储进去的元素,取出时只能先把后存储进去的元素全部取出时才能取出该元素
* 树:
* tree: 它是一种非线性表结构,一对多的关系
* 程序当中的树,是一种生活当中倒挂的树 树根在顶部,树叶和树枝在底部。元素的存储也是通过结点来表达的Node
* 特点:
* 1. 每个结点可以有0-n个子结点
* 2. 没有父节点的结点称为根节点
* 3. 每一个非根节点有且仅有(当且仅当)一个父节点
* 4. 除了根节点外,每个子节点可以分为多个互不相交的子树
* 二叉树--->平衡二叉树---->二叉查找树
* 特点:每个结点当中最多只能有两个子树
* 红黑树--->是二叉树当中非常特殊的一种树
* 约束特点:
* 1. 每个结点可以标记成红色或者黑色(只能使用红黑两种颜色)
* 2. 根节点为黑色
* 3. 每个叶子结点为黑色
* 4. 如果一个结点颜色为红色,那么它的字节点必须为黑色,也就是说一条路径上不可能相邻的两个结点为红色。
* 特点:
* 检索速度非常快。
*
* 图:多对多关系
数组列表集合 ArrayList
* 特点:
* 1. 元素有序
* 2. 元素有索引
* 3. 可以存储重复元素
* 4. 需要进行容器初始化 计算它的初始大小。
* 5. 如果调用的是一个空参构造方法,初始容量为0,当第一次执行add方法时,程序会把空数组转换成一个容量大小为10的数组
* 6. 当容器即将溢出时,需要进行扩容,每次扩容的大小为原来容器的1.5倍。
LinkedList 链表列表集合
* 它是一个双向链表结构
* 特点:
* 1. 不需要容器的初始化
* 2. 元素可重复
* 3. 没有索引下标
* 4. 元素有序的(存储和取出的顺序是一致的)
* 4. 有时候我们可以把LinkedList作为堆栈结构或者队列结构来使用
* 常用的API方法
* 1. void addFirst(E e) 在该列表开头插入指定的元素。
* 2. void addLast(E e) 将指定的元素追加到此列表的末尾。
* 3. E element() 检索但不删除此列表的头(第一个元素)。
* 4. E getFirst() 返回此列表中的第一个元素。
* 5. E getLast() 返回此列表中的最后一个元素。
* 6. boolean offer(E e) 将指定的元素添加为此列表的尾部(最后一个元素)。
* 7. boolean offerFirst(E e) 在此列表的前面插入指定的元素。
* 8. boolean offerLast(E e) 在此列表的末尾添加指定的元素
* 9. E peek() 检索但不删除此列表的头(第一个元素)。读取数据
* 10. E peekFirst() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
* 11. E peekLast() 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。
* 12. E poll() 检索并删除此列表的头(第一个元素)。轮询/头顶
* 13. E pollFirst() 检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。
* 14. E pollLast() 检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。
* 15. E pop() 从此列表表示的堆栈中弹出一个元素。 删除 每次把首节点的元素取出并删除掉
* 16. void push(E e) 将元素推送到由此列表表示的堆栈上。
* 17. E removeFirst() 从此列表中删除并返回第一个元素。
* 18. E removeLast() 从此列表中删除并返回最后一个元素。
HashSet类集合 * 1. 它是Set集合的实现类 * 2. 不允许存储重复元素 * 3. 元素没有索引 * 4. 元素不能保证有序 * 5. 它的底层采用哈希表结构来存储元素 * 6. 它允许存储null元素 * 7. 它必须初始化容器大小 初始为16 负载因子为0.75 * 8. 扩容机制:当容器存储的个数达到了初始容量的3/4--->16*0.75=12,此时容器需要进行扩容 * 常用的API方法: * 1. boolean add(E e) 将指定的元素添加到此集合(如果尚未存在)。 * 2. boolean contains(Object o) 如果此集合包含指定的元素,则返回 true 。 * 3. Iterator<E> iterator() 返回此集合中元素的迭代器。
Set接口集合 * 1. 不允许存储重复的元素 * 2. 元素没有索引 * 3. 它有迭代器,通过迭代器取出Set集合当中的元素值 * 4. set接口的方法和Collection中的方法完全相同
在Set集合当中如何保证元素是不重复的? * hashcode()---->计算该元素的哈希值 * equals() ---->判断元素的值内容是否相同,true--->相同-->过滤不添加; false-->不相同--->添加 * 哈希表结构底层是一个数组结构,每次往数组当中存储的时候,首先计算该元素的哈希值,得出存储数组的位置 * 判断数组的该位置上是否已经存储的元素和该元素的哈希值相同,如果哈希值相同,代表该位置上已经有添加的元素 * 通过equals方法,判断数组位置上的元素和即将添加的元素内容值是否相同,如果相同,不添加 * 如果不相同,直接添加,通过链表结构添加原来元素的后面