/** 结点是数据结构的基础,构成复杂数据结构基本组成单位
* 树(tree):是n个结点的有限集:n=0是空树
* 在任意非空树中,有且只有一个根结点
* n>1时,其余结点可分为m个互不相交的有限集,个数没有限制,但一定互不相交
* 树的定义中,使用了递归的方式,起重要作用
*
* 结点的度:
* 结点拥有子节点的数量成为结点的度
*
* 结点关系:
* 结点子树的根结点称为该节点的孩子结点
* 相应该结点称为孩子结点的父结点(双亲结点)
*
* 结点的层次:
* 有几层就几层
*
* 树的深度:
* 树中结点的最大层次称为树的深度(高度)
*
* 二叉树:
* 二叉树是n个结点的有限集合,如果n=0,那就称为空二叉树
* 特点:
* 每个结点最多只有两颗子树,所以二叉树中不存在度大于2的结点
* 左子树和右子树是有顺序的,次序不能任意颠倒
* 即使树种某个结点只有一颗子树,也要区分它是左子树还是右子树
*
* 二叉树的性质:
* 在二叉树中第i层上最多有2^(i-1)个结点(i>=1)
* 二叉树中如果深度为k,那么最多有2^k-1个结点
* n0=n2+1,n0表示度数为0的结点,n2表示度数为2的结点
* 在完全二叉树,具有n个结点的完全二叉树的深度为[log2n]+1
* 其中[log2n]是向下取整
* 若对含n个结点的完全二叉树从上到下且从左到右进行1到n的编号
* 则对完全二叉树中任意一个编号为i的结点有如下特性:
* 若i=1,则该结点是二叉树的根,无父结点,否则,编号为i/2的结点
* 若2i>n,则该结点无左孩子结点,否则,编号为2i的结点为其左孩子结点
* 若2i+1>n,则该结点无右孩子结点,否则,编号为2i+1的结点为有孩子结点
*
* 斜树:
* 所有的结点都只有左子树的二叉树叫做子斜树,所有结点都是只有右子树的二叉树叫右斜树
*
* 满二叉树:
* 在一颗二叉树中,如果所有分支结点都存在左子树和右子树,并且所有的叶子都在同一层上
* 特点:
* 叶子只能出现在下一层
* 非叶子结点的度一定是2
* 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数也最多
*
* 完全二叉树:
* 对一颗具有n个结点的二叉树按层编号,如果编号为i(i<=<i=n)的结点与同样深度的满二叉树中编号为i的结点位置完全相同
* 这样的就是完全二叉树
*
* 二叉树的存储结构:
* 顺序存储
* 使用一堆数组存储二叉树中的结点,并且结点的存储位置,就是数组的下标
* 当二叉树为完全二叉树,结点数刚好填满数组
* 如果不是完全二叉树,也采用顺序存储,中间会有null,已经出现了空间浪费的情况
*
* 比如右斜树极端情况,采用顺序存储的方式十分浪费空间
* 顺序存储只适用于完全二叉树
*
* 二叉链表
* 顺序存储不能满足二叉树的存储要求,采用链式存储
* 二叉树的每个结点都有两个孩子
* 可以将结点数据结构定义成一个数据和两个指针域
* 数据节点
*
* !!!二叉树的遍历:
* 从根节点出发,按照某种次序依次访问二叉树中所有结点
* 使得每个结点被访问一次,且仅被访问一次
*
* 二叉树的访问次序可以分为四种:
* 递归遍历
* 自上而下,从左到右,每个结点会走3次,
* 前序遍历(从根节点出发,当第一次到达结点时就输出结点数据,按照先向左再向右的方向访问),ABDHIEJCFG 根左右
* 中序遍历(根结点出发,当第二次到达结点时,就输出结点数据,先向左再向右的方向访问),HIDJE 左根右
* 后序遍历(根节点出发,当第三次到达结点时就输出结点数据,按照先向左再向右的方向访问) 左右根
* 层次遍历(按照树的层次自上而下的遍历二叉树,ABCDEFGHIJ)
*
* 二叉查找树:
* 若左子树不为空,子树左边的所有的值要小于它的根结点的值(越来越小)
* 右子树不为空,子树右边的所有值大于根结点的值(越来越大)
* 左右子树也是一个二叉查找树
* 没有键值相等的点
*
* 平衡二叉树(AVL树)
* 含右相同结点的二叉树的不同形态,找出一个查找平均长度最小的一颗二叉查找树
* 要么是一颗空树,要么其根结点左右子树的深度之差的值不超过1
* 左右子树也都是平衡二叉树
* 二叉树结点的平衡因子定义为该结点的左子树的深度减去右子树的深度
* 平衡因子=左子树深度-右子树深度(1/0/-1)
*
* 红黑树
* 自平衡的二叉树,又增加了一个颜色的属性
* 根节点只能是黑色
* 红黑树中,所有的叶子结点后面再接上左右两个空结点可以保持算法的一致性,所有的空结点也是黑色
* 其他的结点要么是黑色,要么是红色,红色结点的父结点和左右孩子结点都是黑色,黑红相间
* 在任意一颗子树中,从根节点向下走到空结点的路径上所经历的黑结点数是相同的,保证是平衡二叉树
*
* B-树(B树):
* 平衡的多路查找树,它在文件系统中很有用,一颗m阶的B树
* 树中每个子结点至多有m颗子树
* 若根节点不是叶子结点,则至少有2颗子树
* 除根节点外所有非终端结点至少有[m/2]颗子树
* 每个结点的信息结构(A0,K1,A1,K2...Kn,An)
* k为关键字,A是指针
* 所有的叶子结点都出现在同一层次上,且不带任何信息,保持算法的一致性
*
* B+树
* B-树和B+树是后续数据库阶段重点应用
*
*
*
* 数组->集合
* int[]arr=new int[]{1,2,3,4,5}
* List.of(arr) List.of(arr)把数组当成一个元素放到集合
* System.out.println(arr1.get(0)[0])
* 集合->数组
* List.toArray()
*
* 尽量指定初始化容量,如果确定不了,默认指定16,每次扩容都很耗资源
* 使用泛型,数据的类型时,一定要使用引用数据类型,包装数据类型
*
* 集合(最重要):
* 动态保存不同类型数据
* 主要分为两大类:
*
* 单列集合(单个对象,存放单值的最大父接口)
* Collection<E> 接口有两个重要的子接口,List和Set,他们的实现子类都是单列
* List<E>(列表)线性表,和数组类似,List可以动态增长
* Set<E>也是线性表,检索元素效率低,删除和插入的效率高
*
* List特点:
* 数据有顺序(先后添加顺序)
* 数据可以重复
*
* 双列集合(双列数据,存放对值的最大父接口)
* Map<K,V> 接口的实现子类是双列集合
* Map(映射)保存具有映射关系的数据,保存着两组数据,key和value
* key不能重复,key和value可以是任意类型的引用数据类型
*
* Collection实现子类可以存放多个元素,每个元素可以是Object
*
* 有些实现类可以放重复元素,有些不可以
* 有些实现类,是有序的(List),有些不是有序(Set)
* Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
*
* Iterator对象称为迭代器,主要用于遍历Collection集合中的元素
* 所有实现类C接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器
* Iterator仅用于遍历集合,Iterator本身并不存放对象
*
* Iterator iterator=coll.iterator() 得到一个集合的迭代器
* iterator.next()遍历并且返回数据
*
* 遍历步骤:
* Collection col=new ArrayList();
* col.add(new Book(.....))
* 1.先得到col对应的迭代器
* Iterator iterator = col.iterator();
* 快捷键:itit
* 2.使用while循环遍历
* while(iterator.hasNext()){判断是否还有数据
* //返回下一个元素,类型是Object,编译类型是Object,运行类型看实际写的
* Object obj=iterator.next();
* System.out.println("obj="+obj)
* }
* 当退出循环后,这时iterator迭代器,是指向最后的元素,再次遍历如下:
* iterator=next()
* 会抛出异常,因为集合中已经没有数据了
* 如果希望再次遍历,需要重置迭代器:iterator=col.iterator();
*
*
* 增强for循环(快捷键:I)
* 增强for循环可以代替iterator迭代器,就是简化版的iterator,本质一样,底层仍然是迭代器,只能用于遍历集合或数组
* 基本语法:
* for(元素类型 元素名:集合名或数组名){
* 访问元素
* }
学习心得:今天学二叉树和集合,难度还好,下午的作业难度有点大,修改密码和注册账户的功能没弄明白