关于二叉树的遍历
深度优先遍历
- 先序遍历,先访问根节点,再访问子树。
- 中序遍历,先访问左子树(右子树),再访问根节点,后访问右子树(左子树)。
- 后序遍历,先访问子树,再访问根节点。
广度优先遍历
- 层次遍历,优先访问离根节点近的节点。
对于树节点的定义
struct TreeNode{
TreeNode* left;
TreeNode* right;
int val;
TreeNode(int t = 0):val(t),left(nullptr),right(nullptr){}
};
先序、中序、后序遍历的递归实现
对于先序遍历,中序遍历,后序遍历。其递归实现较为简单。
//自定义访问函数
void visit(TreeNode* root){}
void preorderTraversal(TreeNode* root){
if(root==nullptr) return;
//访问根节点,自定义访问函数
visit(root);
//再访问子树
preorderTraversal(root->left);
preorderTraversal(root->right);
}
void inorderTraversal(TreeNode* root){
if(root==nullptr) return;
//根节点在访问子树中间访问
preorderTraversal(root->left);
visit(root);
preorderTraversal(root->right);
}
void postorderTraversal(TreeNode* root){
if(root==nullptr) return;
preorderTraversal(root->left);
preorderTraversal(root->right);
//根节点在访问完子树后访问
visit(root);
}
先序、中序、后序遍历的非递归实现
先序遍历
一个简单的想法就是去模拟系统栈。
void preorderTraversal(TreeNode* root){
if(root==nullptr) return;
//模拟系统栈
stack<TreeNode*> _st;
//表示当前节点
TreeNode* tmp = root;
while(!_st.empty()||tmp){
while(tmp){
_st.push(tmp);
//先序遍历,访问根节点
visit(tmp);
//再将左子树加入访问栈
tmp = tmp->left;
}
//当左子树为空
tmp = _st.top();
//弹出其根节点
_st.pop();
//并将当前访问节点设置为右子树
tmp = tmp->right;
}
}
中序遍历
void inorderTraversal(TreeNode* root){
if(root==nullptr) return;
//模拟系统栈
stack<TreeNode*> _st;
//表示当前节点
TreeNode* tmp = root;
while(!_st.empty()||tmp){
while(tmp){
_st.push(tmp);
//再将左子树加入访问栈
tmp = tmp->left;
}
//当左子树为空
tmp = _st.top();
//中序遍历,访问最左节点
visit(tmp);
//弹出其根节点
_st.pop();
//并将当前访问节点设置为右子树
tmp = tmp->right;
}
}
后序遍历
void postorderTraversal(TreeNode* root){
if(root==nullptr) return;
//模拟系统栈
stack<TreeNode*> _st;
//表示当前节点
TreeNode* tmp = root;
//表示上次访问的节点
TreeNode* last = nullptr;
while(!_st.empty()||tmp){
while(tmp){
_st.push(tmp);
//再将左子树加入访问栈
tmp = tmp->left;
}
//当左子树为空
tmp = _st.top();
// 后序遍历
// 右孩子为空或者访问过了
if (tmp->right == nullptr || tmp->right == last) {
visit(tmp->val);
_st.pop();
last = tmp;
tmp = nullptr;
} else {
tmp = tmp->right;
}
}
return;
}
层次遍历
利用队列保存每一层的节点,再依次访问。
void levelOrder(TreeNode* root)
{
if(!root) return;
queue<TreeNode*> q1;
q1.push(root);
TreeNode* t;
int size = 0;
int level = 1;
while(!q1.empty()){
size = q1.size();
for(int i = 0;i<size;++i){
t = q1.front();
visit(t)
if(t->left) q1.push(t->left);
if(t->right) q1.push(t->right);
q1.pop();
}
level++;
}
return;
}