数据结构-树结构(二叉树概念)

220 阅读5分钟

二叉树的概念

我们首先来认识一下什么叫二叉树。顾名思义,二叉树就是树中每个节点最多有两个子节点。

  • 二叉树可以为空,也就是没有节点。
  • 若二叉树不为空,那么它是一棵由一个根节点和两棵互不相交的,分别称作根的左子树(TL)和右子树(TR)组成的非空树;左子树右子树又同样都是二叉树。 二叉树有五种形态 image.png 分别是空树(a)只含一个根节点的二叉树(b)只拥有一个左子节点的二叉树(c)只拥有一个右子节点的二叉树(d)同时拥有左右子节点的二叉树(e)

二叉树的特性

  • 二叉树的第i层最大的节点数为:2^(i-1),i >= 1
  • 深度为i的二叉树有最大节点总数为: 2^i-1,i >= 1
  • 对于任何非空二叉树K,若n1表示叶节点的个数,n2是度为2的非叶节点个数。那么n1 = n2 + 1 image.png

完美二叉树

人无完人,但二叉树有完美二叉树(Perfect Binary Tree),也叫满二叉树(Full Binary Tree)。 image.png
如上图,完美二叉树是指除了最下面的叶子节点(H~O)以外,每层节点都有两个子节点。

完全二叉树

完全二叉树(Complete Binary Tree)又是什么东西?就完完全全是个二叉...不皮了,我百度了:一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。说实话记不住概念,所以总结了以下特性帮助记忆:

  • 除了二叉树的最后一层外,其他各层的节点数都达到最大个数。
  • 且最后一层从左向右的叶节点连续存在,只缺右侧若干节点。
  • 完美二叉树是特殊的完全二叉树。 image.png
    如上图就不是一颗完全二叉树,因为D节点还没有右节点,而E节点已经有了左右节点,不满足完全二叉树的特性。

二叉树的储存

二叉树的存储常见的数据结构是链表和数组

使用数组

使用数组存储完全二叉树是很好的,为什么呢?因为从上至下,从左至右的顺序可以依次存入到数组中如下图: image.png
但是这就是二叉树的完美存储方案吗?并不是。
image.png
这是一颗一般二叉树,它并不能按照从上至下,从左至右的顺序来存储,如果非要这样存储,也只能将它补全成完全二叉树如图:
image.png
如果按照这样补全的方式去使用数组存储,中间会有很多空节点存入数组,造成巨大的资源浪费。

使用链表

使用链表存储二叉树会比数组更加高效,因为我们可以将每个节点封装成一个包含左节点引用,右节点引用,存储的数据这三个元素的Node节点,那么就算不是一颗完全二叉树,只需要把左节点引用或者右节点引用置为null就可以了。 image.png

二叉搜索树

二叉搜索树(BST, Binary Search Tree),又叫二叉排序树或者二叉查找树, 它或者是一棵空树,或者是具有以下性质的二叉树:

  • 若它的左子树不为空,则左子树上所有结点的值都小于根结点的值。
  • 若它的右子树不为空,则右子树上所有结点的值都大于根结点的值。
  • 它的左右子树也分别是二叉搜索树。 举个栗子:
    image.png
    从左至右第一棵树为什么不是二叉搜索树呢?很简单。值为10的节点的右子节点小于了其根节点的值所以不满足搜索二叉树,其他两棵树都满足以上的搜索二叉树的性质。
    二叉搜索树是一个非常经典且高效的一种数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势。再举个栗子:
    image.png
    如果我要查找10这个位置的节点我要怎么找?有一种方法就是将所有的节点依次从左到右从上到下放进数组中后排序,然后一个一个遍历数组,直到查找到10这个节点为止,那么最多要查找10次。你可能会说不就是10次吗?我能找100次,那要是有一百万个节点呢?(手动狗头),还有更离谱的说我能肉眼查找...
    显然这并不是一种很高效的方法,那么能不能有更好的方法呢?肯定是有的。我们可以将刚刚的数组进行二分查找,找打数组中间的数,判断是否比10大,若比10大则取左侧部分的数组,比10小则取右侧部分的数组,然后继续取数组中间的数查找,最终查找到10这个数。这样只需要查找4次就可以找到。
    其实这就是我们说的二分法,把这个方法与二叉树结合起来那就是我们说的二叉查找树,让我们用二叉查找树来解决刚刚的问题。
    image.png
    如图也是4次就找到了目标,原理跟数组的二分查找是一样的。所以说二叉搜索树是一个非常有用的数据结构。