二叉树是一种重要的必须要掌握的数据结构,也是面试官经常问到的。本篇整理一下二叉树的基本操作:遍历。
二叉树的遍历有4种:中序、前序(也叫先序)、后序、层次,前3种属于深度优先搜索(动画演示),后1种属于广度优先搜索(动画演示)。
中序、前序、后序:
中序、前序、后序是根据访问根节点的顺序决定的,先访问根节点叫前序,后访问根节点叫后序,中间访问根节点叫中序,所以他们的访问顺序如下:
中序:左子树 -> 根节点 -> 右子树(动画演示)
前序:根节点 -> 左子树 -> 右子树(动画演示)
后序:左子树 -> 右子树 -> 根节点(动画演示)
递归:
二叉树中常用递归,书写简洁,后面代码多以递归为主。
中序代码:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
visit(root, &ret);
return ret;
}
void visit(TreeNode* root, vector<int> *ret) {
// 左 中 右
if (root == NULL) return;
visit(root->left, ret);
ret->push_back(root->val);
visit(root->right, ret);
}
};
对应leetcode:94. 二叉树的中序遍历
前序代码:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
visit(root, &ret);
return ret;
}
void visit(TreeNode* root, vector<int> *ret) {
// 中 左 右
if (root == NULL) return;
ret->push_back(root->val);
visit(root->left, ret);
visit(root->right, ret);
}
};
对应leetcode:144. 二叉树的前序遍历
后序代码:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
visit(root, &ret);
return ret;
}
void visit(TreeNode* root, vector<int> *ret) {
// 左 右 中
if (root == NULL) return;
visit(root->left, ret);
visit(root->right, ret);
ret->push_back(root->val);
}
};
对应leetcode:145. 二叉树的后序遍历
中序非递归实现:
深度优先搜索非递归实现需要借助栈,中序遍历代码如下,代码比递归实现复杂且难懂。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> st;
// 一直压左子树入栈
TreeNode *p = root;
while (p) {
st.push(p);
p = p->left;
}
while (!st.empty()) {
p = st.top(); st.pop();
ret.push_back(p->val);
p = p->right;
while (p) { // 继续左子树入栈
st.push(p);
p = p->left;
}
}
return ret;
}
};
层次遍历:
按层依次输出,例如下图4,5和7在同一层,层次遍历依次输出:1,2,3,4,5,7,8。(动画演示)
层次遍历需要借助队列实现,将每一层的节点入队列,遍历队列的同时生成下一层的节点队列,代码如下(代码中2层的节点队列使用了同一个变量q存储,通过size来划分):
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> result;
// 层次遍历
queue<TreeNode*> q;
if (root) q.push(root);
while (!q.empty()) {
vector<int> level;
int size = q.size();
for (int i = 0; i < size; i++) {
TreeNode* t = q.front(); q.pop();
level.push_back(t->val);
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
result.push_back(level);
}
return result;
}
};
对应leetcode:剑指 Offer 32 - II. 从上到下打印二叉树 II