简单二叉树的模型和解法(C++)
二叉树的层次遍历
例题:
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
解题思路:
拿到这道题之后,他要求返回节点自底向上的层次遍历,即从叶节点开始向上遍历到根节点,显然,叶子结点无法直接找到。
因此,我们可以采用先从根节点自上而下遍历,然后将遍历的顺序颠倒即可。这样实现起来就会相对方便。
这里先给出代码:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
auto levelOrder=vector<vector<int>>();
if(!root)
return levelOrder;
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
auto level=vector<int>();
auto size=q.size();
for(int i=0;i<size;i++)
{
auto node=q.front();
q.pop();
level.push_back(node->val);
if(node->left)
q.push(node->left);
if(node->right)
q.push(node->right);
}
levelOrder.push_back(level);
}
reverse(levelOrder.begin(),levelOrder.end());
return levelOrder;
}
这里先把上面代码里的我遇到的一些难理解的地方先列出来,然后再分析方法:
1.vector的用法
vector是一个容器函数,具体可以看下面的博客介绍。
链接: https://blog.csdn.net/wkq0825/article/details/82255984
然后这里解释一下上面代码里用到的vector:
vector<vector> A; 定义A = [[0,1,2],[3,4]]
图片:
这是我在网上找到的相对比较好的解释,但具体网址忘掉了。
vectorA 代表建立了一个容器A,
而vector<vector>A则代表一个容器数组,相当于可以在里面装多个容器,因此按上面图片里的操作,可以把B容器放到A中。
A.push_back(4) 表示把4放入容器A中。
2.auto 这是一个数据类型,类似于int,char.只不过他代表不确定,这个数据的类型是他自己运行后得出来的。
3.队列操作
queue<TreeNode*>q;
这代表新建了一个队列q,遵循先进先出的规则。
q.size() 队列大小;
q.empty()
q.front()队列头元素
具体用法可以参考https://blog.csdn.net/weixin_44012745/article/details/87887991.
分析:
现在我们开始分析这个题。
先定义容器,因为我们要逐层遍历,显然,相当于把每一层都分别装进一个容器,最后再放到统一的一个容器里,因此这里先定义levelOrder.
然后,我们这里采用队列的方式,因为是逐层遍历,那每一层遍历结束,就把它放入容器中,开始对下一层进行遍历。因此,用队列先进先出的方式。第一层遍历完了就让第一层pop出去,接着下一层(即第一层的孩子)进队列,然后继续遍历,依次直到最后一层。
即:判断遍历结束的条件为:队列为空,再没有孩子节点进队,代表已经访问完叶节点了。
因为每一层是一个数组,因此采用vector的方式,显然,根节点进队列,队列大小为1,取队头放入容器,然后pop出去,孩子节点进队列。
可以看出,每一次队列的大小刚好就为每一层节点的个数。因此size=q.size(). 依次遍历size下,每pop出去一次,就把他的子节点进队列,当这层所有的节点都pop出去时,剩下的刚好为下一层所有的节点。
这样反复递归遍历,并将所有的容器都装入levelOrder中,然后采用reverse函数将次序颠倒,return即可得到从底向上遍历的结果。