二叉树是一种最简单的树结构,通常由根节点、左子树和右子树组成。常见的二叉树由平衡二叉树、二叉搜索树等。下面笔者将重点介绍一下普通二叉树的前序、中序、后序及层次遍历的原理及代码实现。
二叉树的前序、中序及后序遍历
二叉树的前序、中序及后序遍历中的序指的是访问根节点的顺序。顾名思义,前序遍历的意思就是首先访问根节点并以根节点、左子树、右子树的顺序遍历该二叉树。需强调的一点是在对子树(无论是左子树还是右子树)遍历时其遍历顺序同样为子树的根节点、子树的左子树、子树的右子树。因此,二叉树的遍历利用的就是分治的思想常使用深度优先搜索算法实现。下面笔者将使用C++利用递归和迭代的方法来实现二叉树的前序遍历:
前序遍历(递归):
使用递归的方法重要的是确定递归终止的条件,而在二叉树的遍历中递归条件通常为该二叉树指针为空指针。
class Solution {
public:
void preorder_traversal(TreeNode *root){
if(root==null) return;
cout<<root->val<<endl; // 可用其他语句代替,具体看个人目的
preorder_traversal(root->left);
preorder_traversal(root->right);
}
};
前序遍历(迭代):
迭代的方法难点在于迭代终止条件的设置以及实现遍历顺序,通常二叉树的遍历迭代方法军用借助于栈来实现。
class Solution {
public:
void preorder_traversal(TreeNode *root){
stack<TreeNode*> stk;
if(!root) return;
stk.push(root);
while(!stk.empty()){
root=stk.top();
cout<<root->val<<endl;
stk.pop();
//由于栈的先入后出的性质,因此需要将左节点后入栈从而可以优先访问
if(root->right) stk.push(root->right);
if(root->left) stk.push(root->left);
}
}
};
中序遍历(递归)
中序遍历的顺序是左子树、根节点及右子树。下面是递归实现:
class Solution {
public:
void Inorder_traversal(TreeNode *root){
if(root==null) return;
Inorder_traversal(root->left);
cout<<root->val<<endl; // 可用其他语句代替,具体看个人目的
Inorder_traversal(root->right);
}
};
中序遍历(迭代)
中序遍历首先遍历左子树,因此需迭代至二叉树左子树的最高做子节点,然后进行回溯来遍历二叉树。下面为迭代实现:
class Solution {
public:
void Inorder_traversal(TreeNode *root){
stack<TreeNode*> stk;
if(!root) return; //为空树则直接返回
while(true){
if(root){
stk.push(root); //根节点入栈
root=root->left; //迭代至二叉树最高左子节点
}
else if(!stk.empty()){
root=stk.top() //该节点为二叉树最高左子节点,首先对其进行访问
cout<<root->val<<endl;
stk.pop();
root=root->right; //访问完最高左子节点后需访问该节点的右子树(若存在)
}
else break;
}
}
};
后序遍历(递归)
后序遍历的顺序为左子树、右子树和根节点。递归实现为:
class Solution {
public:
void Postorder_traversal(TreeNode *root){
if(root==null) return;
Postorder_traversal(root->left);
Postorder_traversal(root->right);
cout<<root->val<<endl; // 可用其他语句代替,具体看个人目的
}
};
后序遍历(迭代)
后序遍历的顺序是左右根,可借助前序遍历根左右的结果得到后序遍历。将前序遍历改为根右左的遍历方式再将结果倒序即得到后序遍历的结果。代码如下:
class Solution {
public:
void postorder_traversal(TreeNode *root){
stack<TreeNode*> stk;
vecor<int> res; //存放根右左遍历的结果
if(!root) return; //为空树则直接返回
stk.push(root);
while(!stk.empty()){
root=stk.top();
res.push_back(root->val);
stk.pop();
if(root->left) stk.push(root->left);
if(root->right) stk.push(root->right);
}
reverse(res.begin(),res.end());//将结果倒序得到后序遍历的结果
for(int num:res) cout<<num<<endl;
}
};
二叉树的层次遍历
前面介绍了二叉树的前序、中序及后序的遍历方法,下面将介绍二叉树的层次遍历。所谓层次遍历就是对二叉树进行逐层遍历。该类遍历使用广度优先搜索通常需借助队列来实现,代码实现如下:
class Solution {
public:
void Hierarchical_Traversal(TreeNode *root){
queue<TreeNode*> que;
if(!root) return;
que.push(root);
while(!que.empty()){
root=que.front();
cout<<root->val<<endl;
que.pop();
//从左向右打印,由于队列先入先出的性质因此先让左节点入队列
if(root->left) que.push(root->left);
if(root->right) que.push(root->right);
}
}
};
最后,感谢各位读者耐心看完,笔者会不断更新算法、机器学习方面的知识。感兴趣的同学可以点一份关注,大家一起学习哦。此外,有问题可以评论区评论或者私聊我,很高兴能帮助到大家。