今天是释然发题解的第二十八天,以后会经常和大家分享学习路上的心得,希望和大家一起进步,一起享受coding的乐趣
本文约1400字,预计阅读5分钟
昨天我们学习了二叉树,忘记的小伙伴们可以看一下哦:
二叉树
今天我们来聊一聊二叉树的中序遍历,明天和大家分享二叉树的后序遍历的问题的相关题目:
非递归的中序遍历
实现
我们想一下假如说一棵树是这样的:
[
3,9,20,null,null,15,7
]
这棵树应该长这样:
3
/ \
9 20
/ \
15 7
二叉树的中序遍历和前序遍历不一样,如果左子树始终有结点存在,那么第一个输出的结点门就应该是最左下角的那个,所以当我们把根节点压入栈的时候,我们就需要不断地把左边界压入栈,即不停地
temp=temp.left;
直到找到的那个结点为空为止,这个时候就弹出这个结点,开始找这颗子树的右结点的左子树(虽然讲的非常变扭,其实自己画个图就好)然后不停地找左子树
为什么要不停地找左子树呢?很简单,中序遍历最先需要遍历的就是左子树的左孩子,但是一个结点对于自己的左孩子来说其实就是父亲,不能第一个打印,因此必须不停地找左孩子
最后栈为空时,停止
实现
当我们理解了这个过程以后其实相对就很容易啦!
//非递归的中序遍历
void InOrder(Node root)
{
if (root == null)
{
return;
}
stack<Node> stack;
//vector<int> result;
// 先把根节点压栈
stack.push(root);
while (!stack.empty())
{
if(root!=NULL)
{
stack.push(root);
root=root.left;
}
else
{
root = stack.pop();
cout<<root.val;
root=root.right;
}
}
cout<<" "<<endl;
}
真的就完成了嘛?
我们来测试一组边界数据:假设这棵树只有一个结点存储的是3
3
/ \
NULL NULL
我们把3压栈,这个时候我们再把3压栈,发现无论如何这个3会至少会打印2次,所以这个代码有错误。我们再想想,为啥之前会有一个压栈的操作,就是为了让栈非空,那么我们可以把这句话删除
// 先把根节点压栈
stack.push(root);
然后修改一下这段
while (!stack.empty() || root!=NULL)
这样这个程序就不会中途停止了
我们再来对更多的数据进行测试
3
/ \
9 20
/ \ / \
15 7 2 8
发现是没有问题的,考虑问题一定要考察边界条件,特殊数据这是为什么每次总觉得自己都是对的,但是却不能AC的原因了,希望自己在以后的做题过程中慢慢变好吧
当然咯复杂度的问题也是我们需要考虑的问题,如果能够做到优化和剪枝,那么自己的代码一定也能够让面试官眼前一亮
好了,今天的二叉树的中序遍历就到这里。
释然每天发布一点自己学习的知识,希望1年后我们也能在ACM的赛场上见面,一起去追寻自己的程序猿之路吧!
后期也会和大家一起分享学习心得和学习经验呢,明天我们不见不散哦!
下期预告:
二叉树的后序遍历
如果大家有什么建议或者要求请后台留言,释然也想和大家一起进步呀!
联系方式:shirandexiaowo@foxmail.com