二叉树的最大深度
题目:LeetCode每日一题:
太久没学习了,我去复习了一下二叉树!
树的引入:
更基础的数组和链表都无法兼顾静态操作(查找为例)与动态操作的高效性。而树这种数据结构可以将二者的优点融合.
可以将其理解为:
列表的列表:list < list >
以及:
二维的列表:listlist
树结构带有线性结构的特征,为了与非线性的图结构相区别,可以理解为半线性结构。
连通+无环
如果节点之间均有路径,称之为连通图(connected)
不含环路的话,就称之为无环图(acyclic)
树是一种无环连通图、以及极小连通图、极大无环图。
树中的任一节点与树根之间存在唯一通路。
二叉树 binary tree
直接进入二叉树吧
- 二叉树是节点度不超过2的树
- 同一节点的孩子和子树,均以左、右区分(隐含了树的有序性,一般认为左在先)
- 深度为k的节点,至多有2k个
- 含有n个节点,高度为h的二叉树中 h<n<2h+1
可以看出,其节点数和高度是呈指数关系对应的,对于一颗二叉树而言,如果控制得当,其高度增长的速度会异常缓慢。
这是引入二叉搜索树的重要理论基础。
真二叉树:每个节点的出度都是偶数。
这种添加是假想的,并不需要在实际中严格实现。
用二叉树描述多叉树
二叉树是多叉树的特例,且在有根以及有序时,其描述能力足以覆盖后者。
用==”长子-兄弟“==法:
只要将右图旋转45°
可以将任何一棵一般性的树转化成二叉树。
特殊二叉树
- 满二叉树
一棵高度为h,且含有2h-1个节点的二叉树称为满二叉树,即树中的每层都含有最多的节点。满二叉树的叶子结点都集中在二叉树的最下层,并且除了叶子节点之外每个结点的度数为2。
根据上面的满二叉树描述,可以对满二叉树按照层序编号:约定从根结点编为1开始,自上而下,自左向右。这样,每个结点都对应一个编号,对于编号i的结点,若有双亲,则其双亲为i/2向下取整,若有左孩子,则左孩子为2i;若有右孩子,则右孩子为2i+1。
- 完全二叉树
高度为h、有n个结点的二叉树,当且仅当其每个节点都与高度为h的满二叉树中1~n号结点相对应时,成为完全二叉树。
- 二叉排序树
- 平衡二叉树
二叉树存储结构
- 顺序存储
顺序存储就是用一组地址连续的存储单元自上而下、自左至右存储完全二叉树上的结点元素,即将完全二叉树上编号为i的结点元素存储在一位数组下标为i-1的分量中。
完全二叉树和满二叉树适合采用这种方式。对于一般的二叉树,为了能让数组下标反映二叉树中结点之间的逻辑关系,可以添加一些不存在的空结点。
- 链式存储
顺序存储的空间利用率太低,二叉树一般采取链式存储。
在二叉树中,结点结构通常包括若干数据域和若干指针域,二叉链表至少包含三个域:数据域data、左指针域lchild、和右指针域rchild。
lchild | data | rchild |
---|
在不同的应用中,可以增加某些指针域,比如增加指向父节点的指针后,变成三叉链表的结构。
在有n个结点的二叉链表中,含有n+1个空链域。
二叉树的遍历
二叉树的遍历是按照某条路径访问树中每个结点,使得每个结点均被访问一次,而且仅被访问一次。
常见的遍历方式有先序、中序、后序三种,“序”指的是根节点被访问的时间点。
回到题目
我最先想到的就是用递归的方式直接解决:
递归计算左子树和右子树的最大深度,直到访问到空结点的时候退出。
int maxDepth(struct TreeNode* root){
if (root == NULL){
return 0;
}
int left_depth = 1 + maxDepth(root->left);
int right_depth = 1 + maxDepth(root->right);
return left_depth>right_depth ? left_depth:right_depth;
}
讨论中也有DFS和BFS的做法,日后再学习。