二叉树基础(上):什么样的二叉树适合用数组来存储?

思考题:二叉树有哪几种存储方式?什么样的二叉树适合用数组来存储?

一、树

        树的常用概念及其解释

        父节点、子节点、兄弟结点、根节点、叶子结点;结点的高度、深度、层;树的高度。

    

       上图中,A节点就是B节点的父节点,B节点是A节点的子节点。B、C、D这三个节点的父节点都是同一个节点A,所以它们之间是互称兄弟节点。没有父节点的结点叫做根节点,也就是图中的点E;没有子节点的节点叫做叶子节点或是叶节点,比如图中的G、H、I、J、K、L 都是叶子节点。

      

     举个例子说明一下:

      

 

二、二叉树

1. 概念

  • 二叉树:每个节点最多只有2个子节点的树,这两个子节点分别是左子节点和右子节点。
  • 满二叉树:除了叶子节点以外,每个节点都有左右两个子节点,这种二叉树叫做满二叉树。
  • 完全二叉树:叶子节点都在最底下两层,最后一层叶子节点都是靠左排列,并且除了最后一层,其他层的节点个数都要达到最大,这种二叉树叫做完全二叉树。

2.二叉树的存储

        存储一棵二叉树有两种方法,一种是基于指针或是引用的二叉链式存储法,一种是基于数组的顺序存储法。

2.1 链式存储

       从图中可以看到,每个节点有三个字段,一个存储数据,另外两个是指向左右子节点的指针。只要知道了根节点,就可以通过左右子节点的指针把整棵二叉树串起来。这种存储方式比较常用,大部分二叉树代码都是基于这种存储结构实现的。

         

2.2 顺序存储

      根节点存储在下标为i = 1的位置,那左子节点存储在下标2*i = 2 的位置,右子节点存储在下标为2*i+1 = 3 的位置。以此类推,B节点的左子节点存储在2*i = 2*2 = 4的位置,右节点存储在2*i+1 = 2*2+1=5的位置。

      

        总结:如果节点x存储在下标为i的位置,那么该节点的左节点存储在下标为2*i的位置,右子节点存储在下标为2*i+1的位置。反过来,下标i/2的位置,存储的就是该节点的父节点。通过这种方式,只要知道根节点的存储位置。就可以通过下标计算,把整棵树串起来。

       上面是一棵完全二叉树,仅仅浪费了一个下标为0的存储位置。如果是非完全二叉树,其实会浪费比较多的数组存储空间。例如下面这课非完全二叉树,下标为0,5,7,10,11,12的存储空间,会浪费掉。

       

     所以完全二叉树更适合用数组来存储。

3.二叉树的遍历

       如何将二叉树的所有节点遍历打印出来?经典的有三种方法:前序遍历、中序遍历、后序遍历。其中,前、中、后序,表示的是节点与它的左右子树节点的遍历打印先后顺序。

  1. 前序遍历:对于树中任意节点,先打印这个节点,再打印它的左子树,再打印它的右子树。
  2. 中序遍历:对于树中任意节点,先打印左子树,再打印它本身,最后打印右子树。
  3. 后序遍历:对于树中任意节点,先打印左子树,再打印右子树,最后打印它本身。

    

        实际上,二叉树的前、中、后序遍历就是一个递归的过程,比如前序遍历,就是先打印根节点,再递归地打印左子树,最后递归地打印右子树。

       二叉树遍历的时间复杂度是O(n)。从前面的遍历图可以看出,每个节点最多会被访问2次,所以遍历操作的时间复杂度跟节点的个数n成正比,也就是说二叉树遍历的时间复杂度是O(n)。

     

猜你喜欢

转载自blog.csdn.net/qq_30816517/article/details/86608028