二叉树的遍历
二叉树的遍历是指按照某条搜索路径访问树中的每个结点,使得每个结点均被访问且仅访问一次。
由二叉树的定义可知,遍历一棵二叉树要决定根节点N、左子树L、右子树R的访问顺序。依据从左往右的原则,常见的遍历顺序有先序遍历(NLR)、中序遍历(LNR)、后序遍历(LRN)。
先序遍历
先序遍历是指对于任意结点,先访问它自身,再访问它的左子树,最后访问它的右子树。
举个🌰
按照先序遍历的顺序,访问这颗完全二叉树,它的遍历顺序是:1 2 4 8 9 5 10 11 3 6 12 7
递归实现
// C++
class TreeNode{
// 次数省略数据域
TreeNode *lchild, *rchild; // 左右孩子指针
}
void visit(TreeNode *node){
// 访问操作
}
void preOrder(TreeNode *node){
if(node == nullptr) return;
visit(node);
preOrder(node->lchild);
preOrder(node->rchild);
}
非递归实现
// C++
#include <stack>
void preOrder(TreeNode *node){
std::stack<TreeNode> s;
TreeNode *p = node;
while(p != nullptr || !s.empty()){
if(p == nullptr){
*p = s.top();
s.pop();
p = p->rchild;
}else{
visit(p); // 入栈前访问
s.push(*p);
p = p->lchild;
}
}
}
中序遍历
中序遍历是指对于任意结点,先访问它的左子树,再访问它自身,最后访问它的右子树。
举个🌰
按照中序遍历的顺序,访问这颗完全二叉树,它的遍历顺序是:8 4 9 2 10 5 11 1 12 6 3 7
递归实现
// C++
void inOrder(TreeNode *node){
if(node == nullptr) return;
inOrder(node->lchild);
visit(node);
inOrder(node->rchild);
}
非递归实现
// C++
#include <stack>
void inOrder(TreeNode *node){
std::stack<TreeNode> s;
TreeNode *p = node;
while(p != nullptr || !s.empty()){
if(p == nullptr){
*p = s.top();
s.pop();
visit(p); // 出栈时访问
p = p -> rchild;
}else{
s.push(*p);
p = p->lchild;
}
}
}
后序遍历
后序遍历是指对于任意结点,先访问它的左子树,再访问它的右子树,最后访问它自身。
举个🌰
按照后序遍历的顺序,访问这颗完全二叉树,它的遍历顺序是:8 9 4 10 11 5 2 12 6 7 3 1
递归实现
// C++
void postOrder(TreeNode *node){
if(node == nullptr) return;
postOrder(node->lchild);
postOrder(node->rchild);
visit(node);
}
非递归实现
// C++
#include <stack>
void postOrder(TreeNode *node){
std::stack<TreeNode> s;
TreeNode *p = node;
TreeNode *last_r;
while(p != nullptr || !s.empty()){
if(p == nullptr){
*p = s.top();
if(p->rchild != nullptr && p->rchild != last_r){
// 右子树存在,且未被访问过,则向右
p = p->rchild;
}else{
// 左右子树都不存在或者都已被访问时,访问自身。
s.pop();
visit(p); // 出栈时访问
last_r = p;
p = nullptr;
}
}else{ // 向左访问到最左边
s.push(*p);
p = p->lchild;
}
}
}
层次遍历
层次遍历是按照层序,自上而下,从左往右访问。事实上,这和BFS(广度优先搜索)的思想一致。
举个🌰
按照层次遍历的顺序,访问这颗完全二叉树,它的遍历顺序是:1 2 3 4 5 6 7 8 9 10 11 12
非递归实现
// C++
#include <queue>
void levelOrder(TreeNode *node){
std::queue<TreeNode> q;
TreeNode *p;
q.push(*node);
while(!q.empty()){
*p = q.front();
q.pop();
visit(p);
if(p->lchild != nullptr) q.push(*p->lchild);
if(p->rchild != nullptr) q.push(*p->rchild);
}
}
全篇至此结束,感谢大家阅读!