二叉树的遍历是指访问二叉树中每一个节点的过程。根据访问节点的顺序,遍历可以分为不同的类型。主要有以下几种遍历方式:
- 前序遍历 (Pre-order Traversal)
访问顺序:
根节点
左子树
右子树
递归实现:
void preOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 访问根节点
std::cout << root->val << " ";
// 递归遍历左子树
preOrder(root->left);
// 递归遍历右子树
preOrder(root->right);
}
非递归实现(使用栈):
#include <stack>
void preOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
std::stack<TreeNode*> s;
s.push(root);
while (!s.empty()) {
TreeNode* node = s.top();
s.pop();
std::cout << node->val << " ";
// 先压入右子树,然后压入左子树,因为栈是后进先出
if (node->right != nullptr) {
s.push(node->right);
}
if (node->left != nullptr) {
s.push(node->left);
}
}
}
- 中序遍历 (In-order Traversal)
访问顺序:
左子树
根节点
右子树
递归实现:
void inOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 递归遍历左子树
inOrder(root->left);
// 访问根节点
std::cout << root->val << " ";
// 递归遍历右子树
inOrder(root->right);
}
非递归实现(使用栈):
#include <stack>
void inOrder(TreeNode* root) {
std::stack<TreeNode*> s;
TreeNode* current = root;
while (current != nullptr || !s.empty()) {
while (current != nullptr) {
s.push(current);
current = current->left;
}
current = s.top();
s.pop();
std::cout << current->val << " ";
current = current->right;
}
}
- 后序遍历 (Post-order Traversal)
访问顺序:
左子树
右子树
根节点
递归实现:
void postOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
// 递归遍历左子树
postOrder(root->left);
// 递归遍历右子树
postOrder(root->right);
// 访问根节点
std::cout << root->val << " ";
}
非递归实现(使用两个栈):
#include <stack>
void postOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
std::stack<TreeNode*> s1, s2;
s1.push(root);
while (!s1.empty()) {
TreeNode* node = s1.top();
s1.pop();
s2.push(node);
// 先压入左子树,然后压入右子树,因为栈是后进先出
if (node->left != nullptr) {
s1.push(node->left);
}
if (node->right != nullptr) {
s1.push(node->right);
}
}
while (!s2.empty()) {
std::cout << s2.top()->val << " ";
s2.pop();
}
}
- 层序遍历 (Level-order Traversal)
访问顺序:
从上到下
从左到右
实现(使用队列):
#include <queue>
void levelOrder(TreeNode* root) {
if (root == nullptr) {
return;
}
std::queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
std::cout << node->val << " ";
// 先加入左子树,然后加入右子树
if (node->left != nullptr) {
q.push(node->left);
}
if (node->right != nullptr) {
q.push(node->right);
}
}
}
总结
前序遍历:访问根节点,递归遍历左子树,递归遍历右子树。
中序遍历:递归遍历左子树,访问根节点,递归遍历右子树。
后序遍历:递归遍历左子树,递归遍历右子树,访问根节点。
层序遍历:使用队列逐层访问节点。
这些遍历方式在不同的场景中有不同的应用,例如前序遍历用于复制树,中序遍历用于排序检查,后序遍历用于释放资源,而层序遍历用于按层级处理树结构。