面试中常考到树的前序,中序,后序和层序遍历,这篇博文就带你深度剖析一下二叉树的各类遍历算法的实现
二叉树的遍历主要有四种,前序、中序、后序和层序
遍历的实现方式主要是:递归和非递归
递归遍历的实现非常容易,非递归的实现需要用到栈,难度系数要高一点。
一、二叉树节点的定义
二叉树的每个节点由节点值、左子树和右子树组成。
class TreeNode{
public:
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
}
二、二叉树的遍历方式
前序遍历:先访问根节点,再访问左子树,最后访问右子树
中序遍历:先访问左子树,再访问根节点,最后访问右子树
后序遍历:先访问左子树,再访问右子树,最后访问根节点
层序遍历:每一层从左到右访问每一个节点。
举例说明:(以下面的二叉树来说明这四种遍历)
前序遍历:ABDFGHIEC
中序遍历:FDHGIBEAC
后序遍历:FHIGDEBCA
层序遍历:ABCDEFGHI
大家可以根据这个例子先熟悉一下这四种遍历,如有不懂的,建议先去google一下,再接着阅读本文
三、前序遍历
递归版本
按照遍历的顺序很容易就能写出下列代码:
以下代码均在leetcode测试通过,二叉树前序遍历的原题链接:戳我!leetcode直通车!上车啦!
vector<int> preorderTraversal(TreeNode* root){
vector<int> ret;
dfsPreOrder(root,ret);
return ret;
}
void dfsPreOrder(TreeNode* root,vector<int> &ret){
if(root==NULL) return;
ret.push_back(root->val);//存储根节点
if(root->left!=NULL) dfsPreOrder(root->left,ret);//访问左子树
if(root->right!=NULL) dfsPreOrder(root->right,ret);//访问右子树
}
非递归版本
非递归版本需要利用辅助栈来实现
- 1.首先把根节点压入栈中
- 2.此时栈顶元素即为当前根节点,弹出并访问即可
- 3.把当前根节点的右子树和左子树分别入栈,考虑到栈是先进后出,所以必须右子树先入栈,左子树后入栈
- 4.重复2,3步骤,直到栈为空为止
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
if (root==NULL) return ret;
stack<TreeNode*> st;
st.push(root);
while(!st.empty())
{
TreeNode* tp = st.top();//取出栈顶元素
st.pop();
ret.push_back(tp->val);//先访问根节点
if(tp->right!=NULL) st.push(tp->right);//由于栈时先进后出,考虑到访问顺序,先将右子树压栈
if(tp->left!=NULL) st.push(tp->left);//将左子树压栈
}
return ret;
}
四、中序遍历
递归版本
中序遍历的访问顺序依次是左子树->根节点->右子树,按照递归的思想依次访问即可
以下代码均在leetcode测试通过,二叉树中序遍历的原题链接:戳我!leetcode直通车!上车啦!