ArrayList和链表以及红黑树笔记记录

ArrayList

底层:在构造一个包含指定元素的列表初始化方法中,1.8中Collection转换Object[]时会有问题 可能出现转换出来不是Object[]类型,因为每个集合的toArray方法都不一样,所以需要和elementData数组进行对比是否为Object[],如果不是Object[],则需要copyOf进行数组转换,底层实际上用了system.arraycopy方法转换数组

如果没有任何参数 则初始化一个长度为10的数组

扩容:添加的时候进行添加末尾,进行size+1,如果数组为空的话,minCapacity(最小容量)就等于size+1,就等于1,空的数组放不了数据,然后就通过max方法进行默认容量和minCapacity进行大小比较取最大值,所以就将minCapacity变为10,初始容量就是10,默认大小,然后第一次进来初始容量是10,再之后进来需要的容量大于10,开始扩容,扩容时新数组的大小=老数组的大小+老数组大小>>1(将老数组大小向右移动一位,获得老数组大小的一半),相当于1.5倍扩容,进行各种判断

failFast机制:创建迭代对象时将全局的modCount赋值给迭代器的局部变量expectedModCount,在迭代的过程中,modCount!=expectedModCount迅速抛出异常。

原理:同时两个线程执行,a线程执行add方法,b线程执行迭代查询方法,调用next方法,在b线程查询的一瞬间初始化迭代器的时候,比如初始化的expectedModCount为值为8,但是此时a线程也在进行add添加方法,add的时候会对modCount进行++操作,modCount和expectedModCount的两个变量的值就不一样,导致了failFast机制。因为ArrayList是线程不安全的,所以会出现这种问题,解决办法呢就是使用Collections工具类中的synchronizeLIst方法进行同步处理,变为线程安全的

单向链表

单项链表只可以从前往后找,最前面为一个虚拟空节点,为了使得插入第一条数据不用去判断他是不是头节点,添加的时候比如在索引2的位置插入node值100,就可以用prev.next(prev表示索引位2的前一个索引位)指向这个node节点,node.next(node表示要插入的索引值)指向原先prev.next指向的位置,就可以得出node.next=prev.next prev.next=node

删除节点的时候,需要找到要删除节点的前一个节点prev,要删除的节点为delNode,需要prev.next指向delNode.next指向的位置,就是删除节点的下一个节点,最后要把delNode赋值null,让gc进行回收,得出

prev.next=delNode.next delNode=null,注意一点就是不能直接把delNode直接指向delNode.next即delNode=delNode.next,导致delNode无法删除

双向链表

LinkedList就是基于双向链表进行的,除了继承list,还会实现一个队列,add方法有两种方式,

1、add方法中的linkLast:表示向尾部去加数据

 

 

三个构造参数l表示指向的前一个节点,e表示当前加入的节点,next指向的是下一个节点,因为是在尾部加数据,所以指向的下一个节点为null

2、push中的linkFirst:表示向头部去添加数据

 

 

prev跟上面一样指向前一个节点,因为这个方法是向头部添加,所以当前添加的位置就是头部,前面没有任何的节点,e表示当前添加的数据节点,f表示当前数据的下一个节点位置

二叉树

概念:每个节点最多只能有两个子节点,子节点分为左节点和右节点

满二叉树

条件:所有非叶子节点都存在左子树和右子树,并且所有叶子都在最后一层的二叉树

叶子节点只能在最后一层、非叶子节点的度一定是2、同样深度的二叉树中,满二叉树的节点个数最多,叶子树最多

 

 

完全二叉树

条件:如过该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续

 

 

二叉搜索树--BST

也叫二叉排序树,任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大,如果相同的值,可以将该节点放在左子节点或右子节点

 

 

二叉搜索树的深度优先遍历分为:前序遍历,中序遍历,后序遍历

前序遍历:先输出父节点,在遍历左子树和右子树

中序遍历:先遍历左子树,在输出父节点,在遍历右子树,中序遍历的结果是有序的

后序遍历:先遍历左子树,在遍历右子树,最后输出父节点

  

二叉搜索树的问题:

比如数据(1,2,3,4,5,6),创建BST

 

 

  1. 左子树全部为空,更像一个单链表

  2. 插入速度没有影响

  3. 查询速度明显降低

  4. 解决方案是平衡二叉树

平衡二叉树--AVL

也叫平衡二叉搜索树,必须满足BST的特征

任意一个节点,平衡因子的绝对值不超过1

  • 某节点的高度值=max(左子树高度,右子树高度)+1

  • 每个节点的左子树和右子树的高度差叫做平衡因子(左右子树高度差为:左子树高度和右子树高度两边值的差不大于1)

 

 

因为计算平衡因子出现2,大于了1,所以要经过右旋和左旋来解决不平衡问题

右旋过程:ps:左旋同理

 

 

R.right=N N.left=T3 R=root(根节点)

 

 

缺点:当频繁的去插入和删除的时候,AVL性能就大大折扣,效率比较低,出现在左右旋的时候,每个节点也只能存一个数据,对节点的利用率差

红黑树

前提:研究红黑树时叶子节点指的是最后的空节点(我们原来理解的叶子节点的孩子节点),就是每个叶子节点下面分别指的左右nil空节点

根节点是黑色的、每个叶子节点都是黑色的(红色节点向左倾斜叫做左倾红黑树)、如果一个节点是红色的,那么他的孩子节点都是黑色的、从任何一个节点到叶子节点,经过的黑色节点个数是一样的

2-3树

  • 每个节点都是可以存放一个元素或者两个元素

  • 存放一个元素的节点称为2-节点,存放两个元素的称为3-节点

  • 每个节点有两个或三个元素的树称为2-3树,2-3树满足二叉搜索树的基本性质

  • 2-3树是绝对平衡的树

 

 

前提:满足二叉搜索树的特征、维持绝对平衡、不能往null节点插入数据

添加2-3树的规律:如上图,原刚开始添加为42,出现一个一元素二节点,再添加一个50,出现一个二元素三节点,并且42和50是在同一行,因为元素不能往null节点插入,因为42左右子节点都是空,所以50放到42右边,紧接着再放入一个33,33比42小,所以放在42左边,此时为一个三元素四节点,2-3树每个节点只可以存放一个或两个元素,此时为三个元素,所以要开始分裂,最后分裂为二叉搜索树形式,分别将33和50放到42的左右节点,以此类推往后接着放元素,进行添加、分裂,维持平衡

  • 2-3树中添加一个新元素,或者添加到2-节点或者添加到3-节点

  • 添加到2-节点,形成一个3-节点

  • 添加到3-节点,暂时形成一个4-节点,然后把4节点进行分裂

  • 如果待融合的节点是3-节点的叶子节点,父节点是2-节点,那么插入的时候要保持绝对平衡,在插入左边的3-节点时称为了四节点,此时要分裂,然后出现不平衡,然后需要吧开始分裂的节点进行融合包吃绝对平衡,下图

 

 

  • 如果待融入的节点是3-节点的叶子节点,父节点也是3-节点,则需要分裂、融合、分裂,直到平衡为止,下图

 

 

2-3树和红黑树等价性,看三张图的变化过程

2-3树格式

 

 

2-3树演变红黑树(半)

 

 

完整左倾红黑树形式

  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值