树的学习1

概念:树表示的是1对多的关系。

定义(逻辑结构):树(Tree)是n( n>=0 )个结点的有限集合,没有结点的树称为空树,在任意一颗非空树中:

有且仅有一个特定的称为根(root)的结点
当n>1的时,其余结点可分为 m( m>0 ) 个互不相交的有限集T1,T2,…, Tm,其中每一个集合 Ti 本身又是一棵树,并且称之为根的子树。

注意:树的定义是一个递归定义,即在树的定义中又用到树的概念。

  1. 结点的层级从根开始定义,根为第一层,根的孩子为第二层。若某结点在第i层,则其孩子就在i+1层。
  2. 对任意结点ni,ni的深度为从根到ni的唯一路径的长。因此,根的深度为0。
  3. 结点ni 的是从ni 到一片树叶的最长路径的长。因此,所有树叶的高都为0。
  4. 一颗树的高等于它根的高。一颗树的深度等于它最深的树叶的深度; 该深度总是等于这棵树的高。

性质:E = N - 1

二叉树

概念:二叉树是一棵树,它的特点是每个结点至多有两棵子树。并且,子树有左右之分,其次序不能颠倒(有序)。

特殊的二叉树:完全二叉树、满二叉树和完美二叉树。

二叉树的性质:
  1. 二叉树在第 i 层至多有 2^(i-1) 个节点
  2. 层次为 k 的二叉树至多有 2^k - 1 个节点(完美二叉树)
  3. 对任何一颗二叉树 T,如果其叶子节点数为 n0 , 度为2的节点数为 n2,则n0 = n2 + 1
  4. 具有 n 个节点的完全二叉树,树的高度为 log2n (向下取整)。
  5. 如果对一颗有 n 个结点的完全二叉树的结点按层序从1开始编号,则对任意一结点有:(堆排序)
    如果编号 i 为 1,则该结点是二叉树的根;
    如果编号 i > 1,则其双亲结点编号为 parent(i) = i / 2
    若 2i > n 则该结点没有左孩子,否则其左孩子的编号为 2i,
    若 2i + 1 > n 则该结点没有右孩子,否则其右孩子的编号为 2i + 1。
二叉树的存储结构
顺序映像非顺序映像(推荐)
按照完全二叉树进行编号,将编号为i的元素存储到数组索引为i的地方。以链表的形式来存储数据元素以及数据元素之间的关系。

*:顺序映像的缺点:1. 代码可读性差!(索引表示)

  1. 当树比较稀疏的时候,将极大的浪费内存空间。在最坏的情况下,一棵只有 k 个结点的单支树,却需要一个长度为 2k 的数组来存储。
二叉树的遍历

遍历对线性结构来说,是一个容易解决的问题,但是对于二叉树则不然。因为二叉树是一种非线性结构,每个结点都有可能有两颗子树,因而需要寻找一种规律,以便使二叉树上的结点能排列在一个线性队列上,从而便于遍历。

深度优先遍历

我们再来回顾一下二叉树的递归定义,可知,二叉树由3部分组成:根,左子树和右子树,因此如果能遍历这三个部分,便是遍历了整个二叉树。

假如以L, D, R分别表示左子树,根结点和右子树,则可能有DLR, LDR, LRD, DRL, RDL, RLD这六种遍历方案。

若限定先左后右,则只有DLR, LDR, LRD 这3种情况,分别称之为先 (根) 序遍历,中(根)序遍历,和后 (根) 序遍历。三者的区别主要在于访问根结点的先后顺序。(时间复杂度 0(N)、实现用栈)

广度优先遍历

广度优先遍历又叫层级遍历。简单来说,就是从上到下,从左到右依次遍历。(实现用队列)

二叉树的建树

有些情况下,我们已知的是二叉树的某个或某些遍历序列。我们需要根据这些遍历序列,构建出一棵”相等”的二叉树,这个过程就叫做二叉树的建树。

只知道前序、中序或中序、后序,就可以构建出一棵二叉树。

在这里插入图片描述

二叉搜索树

又叫二叉排序树。要求树中的结点可以按照某个规则进行比较。(中序遍历有序)

  1. 左子树中所有结点的key比根结点的key小,并且左子树也是二叉搜索树。
  2. 右子树中所有结点的key比根结点的key大,并且右子树也是二叉搜索树。

在BST中存储key相同的对象的方法:

  1. 可以在结点添加一个count属性。

  2. 拉链法, 在结点添加一个next指针域。

  3. 左子树 <= (右子树 >=)

API:
    增:
        boolean add(E e)
    删:
        void clear()
        boolean remove(Object obj)
    查:
        boolean contains(Object obj)
        E min()
        E max()
    遍历:
        List<E> preOrder()
        List<E> inOrder()
        List<E> postOrder()
        List<E> levelOrder()
    获取集合属性:
        int size()
        boolean isEmpty()
    建树:
        static BinarySearchTree buildTree(List preOrder, List inOrder)
问题1:在Java中什么样的对象可以进行比较?
    实现Comparable接口的对象。
问题2:我们实现的BST,添加,删除和查找的时间复杂度是多少呢?
    O(h) h是树的高度
问题3:我们不能够保证树的平衡。因为我们删除度为2的结点,都是在右子树中删除。
    动态添加和删除元素时,会导致树往左倾斜,最坏情况下会退化成链表。

自平衡二叉搜索树:
    AVL树:对任意一个结点而言, 左子树和右子树的高度不超过1.树的高度 h = O(log(n))
    红黑树:通过红黑规则, 保证树的高度也时O(log(n))

AVL VS 红黑树:
    查找:AVL
    添加:红黑树
    删除:红黑树
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值