l2-004 这是二叉搜索树吗?_二叉树初探

7964a38269cc99d044733dd9222dbcd6.png

要知道二叉树是一种特殊的树,了解二叉树之前就需要知道什么是树啦。

1 树

树是n个(n>=0)结点的有限集,n=0的时候称为空树。呵,空树有什么意思?

7f3088be-692d-eb11-8da9-e4434bdf6706.png

在任意一个非空的树中,都满足这两个特性:

  1. 有且仅有一个根结点;
  2. n>1的时候,其余结点可以分成m(m>0)个互不相交的有限集,且每一个集合本身又是一颗树,称为根的子树;

需要注意:根节点只有一个,子树可以有多个,但是一定互不相交!

813088be-692d-eb11-8da9-e4434bdf6706.png
二叉树

如图,只有一个根结点1,但是每个结点的子树个数可以任意,有1个的,也有3个的。

几个概念

  • 结点的度

结点拥有的子树数目称为该节点的度。

32c3b485975bd361a556c7100c59b3f0.png
二叉树的度
  • 结点关系

父结点:如上图,1为2的父结点。

子结点:2为1的子结点。

兄弟结点:父结点相同的结点互为兄弟结点,2,44,6互为兄弟结点。

  • 结点层次

从根开始定义,根为第0层,根的子结点为第1层,以此类推;

树的基本概念介绍到这里,是时候请出真正的主角了!

2 二叉树

二叉树是每个结点最多有两个子结点的树结构。

有且仅有一个根结点,对左右子树严格区分。

有两个特性

  • 二叉树每个结点的度都小于等于2;
  • 第k层结点的最大个数为2^(k-1);

44b7b52053ef6554be5354a0506392d2.png

下面介绍几种特殊的树,应用也非常广泛啦~

3 满二叉树

假设一棵树的深度为k,那么具有2^k-1个结点的二叉树就叫做满二叉树。

1cba497d673e260def90bebec095ee07.png
满二叉树

每一层上的结点数都是最大结点数,第i层就有2^(i-1)个结点;

大白话:就是说除了最后一层结点没有任何子结点外,余下每一层上结点都有两个子结点;

有人要问了,2^k-1是什么鬼,咋来的?

对于一个满二叉树,第一层1个结点,第二层2个结点,第三层4个结点,以此类推,第k层就有2^(k-1)个结点,总结点数就是(1+2+4+…+2^(k-1))=2^k-1。

这里用到等比数列求和公式。

4 完全二叉树

完全二叉树的概念是由满二叉树引出的;

4.1 一个判断准则

如果二叉树的层数为k,那么满足下面两个条件的即为完全二叉树:

  1. 除了第k层,其他(1~k-1)层的结点数都达到最大个数(就是每个结点都有两个子结点,度为2);
  2. 第k层所有结点都连续集中在最左边

因此完全二叉树有如下特性

  • 所有的叶结点都在第k层或第k-1层;
  • 对于任意一个结点,如果他的右子树最大层次为L,那么他左子树的最大层次一定为L或者L+1;

26878be87ba37ef4c2bb7647d27d1a0e.png

完全二叉树1:

23b9a0601079563b8f2737bd1375162f.png

不完全二叉树1:违背条件1,倒数第二次的节点数量不是最大。

cc098533e574923e14fd83067866ef79.png

不完全二叉树2:违背条件2,最后一层的结点没有连续集中在最左侧。(二叉树对于左右子树严格区分)

44b7b52053ef6554be5354a0506392d2.png

4.2 另一个判断准则

假定二叉树的编号是按照从上到下,从左到右的顺序编号,那么对于深度为K的,有n个结点的二叉树,当且仅当

其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。

67e11a48dd1061e621e3512033769641.png

其实也就想表达第一个判断准则中两个条件的意思啦。

一些小性质

假设完全二叉树的结点总数是n,n0表示度为0的结点数,n1表示度为1的结点数,n2表示度为2的结点数。

  • 因此有n=n0+n1+n2;
  • 度为2的结点有两个子结点,度为1的结点有一个子结点,在加上一个根结点,所以有n=1+n1+2*n2;
  • 根据完全二叉树的定义,可以知道n1=0或者1,只有这两种情况。

5 斜树

斜树是二叉树的极端情况。左斜树:所有结点都只有左子树的二叉树;

6652efe4ae111ef8715fe2edc579a1f4.png

右斜树:所有结点都只有右子树的二叉树;​

9c7c671a3afd215d495d773fbc561181.png

6 二叉树的存储

顺序存储

使用一维数组存储二叉树中的节点,先对二叉树进行从上到下,从左到右编号,节点所在编号就是其在一维数组中的索引;

不逼逼废话,举例最直观了。

63a505ec368ea25ace2b3aefb4a773c9.png

对下面这个完全二叉树进行顺序存储,这里为了简便,每个结点的值也是该结点的编号。

67e11a48dd1061e621e3512033769641.png

f6d65ffd9a349d39e3e5ba8f636ab316.png

二叉树是完全二叉树或者是满二叉树的时候,结点数=数组数,刚好填满

噢哟,那很不错哦!

fd05515e64927ae44329d2f9e927d63c.png

当二叉树是不完全二叉树的时候,如果采取顺序存储,会出现空间浪费

什么?这是人家不想看到的呢!

cad004b91e4e9dccd0f9ac74bbfe8288.png

如对下面这个不完全二叉树进行顺序存储,其中灰色表示缺失的节点,虽然缺失,但是编号的时候还是按照满二叉树结点形式进行编号;

bd1630cf140947fb49514c843882f47f.png

c335844a012f55365845946709fc4c78.png

数组中的#就表示此处没有存储结点。

极端情况如斜树,采取顺序存储的方式是十分浪费空间的;

d845d1be5c33a0f04099e8af1d9139a3.png

8bdfd2e797715f92ebbc715bf300bc99.png

这都浪费了一半了吗?

068fdd41af8cddbcfc1dccdff1054157.gif

这怎么能忍!

链表存储

好在我们还有大招!二叉树每个结点最多有两个子结点,因此将结点的数据结构定义为一个数据和两个指针域,分别表示结点值和左右子结点;

每个指针可以准确指向子结点,因此链表存储能够有效利用空间,避免浪费。

 struct TreeNode {     int val;     TreeNode *left;     TreeNode *right;     TreeNode(int x) : val(x), left(NULL), right(NULL) {} };

ce756f2f33a5e33b3bccd6389202e440.png

7 二叉树的遍历

根据根结点的遍历顺序,分为前中后三种遍历方法。

  • 前序遍历:根结点-左结点-右结点
  • 中序遍历:左结点-根结点-右结点
  • 后序遍历:左结点-右结点-根结点

这三种遍历可以用递归或者栈的方法实现。还有一种

  • 层次遍历:从上至下,逐层遍历

一般用递归或队列的方式实现。

23b9a0601079563b8f2737bd1375162f.png

对于上图所示的二叉树,前序遍历:1,3,3,5,6;中序遍历:3,2,5,1,6;

后序遍历:3,5,2,6,1;

层次遍历:1,2,6,3,5;

到这里二叉树的基础知识就讲完啦,是不是有种原来如此的感觉?

df872a5e4d7cac809ad86f2323705819.gif

呼呼~最后和我大喊一声妈妈,我也知道什么叫二叉树啦!

以上内容改编自于我的算法公众号,如果觉得我写的还不错的话,关注我吧!

公众号搜索:易行时光

里面有更多有关算法和数据结构的知识哦,从此小白也能搞懂算法啦~

10b3fe8a08e88befe3422f9860d6319f.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值