面试经典算法20 - 二叉树的前序遍历
LeetCode.144
公众号:阿Q技术站
问题描述
给你二叉树的根节点 root
,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]
示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]
提示:
- 树中节点数目在范围
[0, 100]
内 -100 <= Node.val <= 100
思路
递归
- 使用递归进行前序遍历,即根节点 -> 左子树 -> 右子树。
- 对于每个节点,先将节点的值加入结果数组,然后递归遍历左子树和右子树。
迭代
遍历,先将根节点压入栈中。然后循环执行以下操作:
- 弹出栈顶节点,如果节点为空,则继续弹出,直到遇到非空节点。
- 对于非空节点,先将其值加入结果数组,然后将右子节点压入栈中,再将左子节点压入栈中,保证左子节点在右子节点之前被访问。
图解
这里给大家图解一下迭代的方法。
- 先将根节点压入栈中。
- 当栈不为空时,弹出栈顶元素,遍历右子节点,再遍历左子节点。
- 依次弹出栈顶元素,并添加到结果集。
参考代码
C++
递归
#include <iostream>
#include <vector>
#include <stack>
#include <unordered_map>using namespace std;// 定义二叉树节点
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;preorder(root, result);return result;}void preorder(TreeNode* root, vector<int>& result) {if (root == nullptr) {return;}result.push_back(root->val); // 将当前节点的值加入结果数组preorder(root->left, result); // 递归遍历左子树preorder(root->right, result); // 递归遍历右子树}
};// 创建二叉树
TreeNode* createTree() {TreeNode* root = new TreeNode(1);root->right = new TreeNode(2);root->right->left = new TreeNode(3);return root;
}// 打印结果
void printResult(const vector<int>& result) {cout << "前序遍历结果:";for (int val : result) {cout << val << " ";}cout << endl;
}int main() {Solution sol;TreeNode* root = createTree();vector<int> result = sol.preorderTraversal(root);printResult(result);return 0;
}
迭代
#include <iostream>
#include <vector>
#include <stack>using namespace std;// 二叉树节点的定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};// 非递归前序遍历
vector<int> preorderTraversal(TreeNode* root) {vector<int> result; // 存储遍历结果的数组if (!root) return result; // 如果根节点为空,直接返回空数组stack<TreeNode*> st; // 辅助栈,用于存储遍历过程中的节点st.push(root); // 将根节点入栈while (!st.empty()) { // 当栈非空时循环执行以下操作TreeNode* node = st.top(); // 获取栈顶节点st.pop(); // 弹出栈顶节点result.push_back(node->val); // 将节点值加入结果数组if (node->right) { // 如果节点有右子节点,将右子节点入栈st.push(node->right);}if (node->left) { // 如果节点有左子节点,将左子节点入栈st.push(node->left);}}return result; // 返回结果数组
}// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {if (index >= nodes.size() || nodes[index] == -1) {return nullptr; // 如果节点为空,则返回nullptr}TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点root->left = createTree(nodes, 2 * index + 1); // 创建左子树root->right = createTree(nodes, 2 * index + 2); // 创建右子树return root; // 返回当前节点
}// 销毁二叉树
void destroyTree(TreeNode* root) {if (!root) return; // 如果根节点为空,直接返回destroyTree(root->left); // 递归销毁左子树destroyTree(root->right); // 递归销毁右子树delete root; // 删除当前节点
}int main() {vector<int> nodes = {1, 2, 3, -1, -1, 4, 5}; // 定义二叉树的先序遍历序列TreeNode* root = createTree(nodes, 0); // 创建二叉树vector<int> result = preorderTraversal(root); // 进行非递归前序遍历for (int val : result) { // 输出遍历结果cout << val << " ";}cout << endl;destroyTree(root); // 销毁二叉树return 0;
}
Java
import java.util.*;// 二叉树节点的定义
class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val = x; }
}public class Main {// 非递归前序遍历public List<Integer> preorderTraversal(TreeNode root) {List<Integer> result = new ArrayList<>(); // 存储遍历结果的数组if (root == null) return result; // 如果根节点为空,直接返回空数组Stack<TreeNode> stack = new Stack<>(); // 辅助栈,用于存储遍历过程中的节点stack.push(root); // 将根节点入栈while (!stack.isEmpty()) { // 当栈非空时循环执行以下操作TreeNode node = stack.pop(); // 获取栈顶节点result.add(node.val); // 将节点值加入结果数组if (node.right != null) { // 如果节点有右子节点,将右子节点入栈stack.push(node.right);}if (node.left != null) { // 如果节点有左子节点,将左子节点入栈stack.push(node.left);}}return result; // 返回结果数组}// 创建二叉树public TreeNode createTree(int[] nodes, int index) {if (index >= nodes.length || nodes[index] == -1) {return null; // 如果节点为空,则返回null}TreeNode root = new TreeNode(nodes[index]); // 创建当前节点root.left = createTree(nodes, 2 * index + 1); // 创建左子树root.right = createTree(nodes, 2 * index + 2); // 创建右子树return root; // 返回当前节点}// 销毁二叉树public void destroyTree(TreeNode root) {if (root == null) return; // 如果根节点为空,直接返回destroyTree(root.left); // 递归销毁左子树destroyTree(root.right); // 递归销毁右子树}public static void main(String[] args) {Main solution = new Main();int[] nodes = {1, 2, 3, -1, -1, 4, 5}; // 定义二叉树的先序遍历序列TreeNode root = solution.createTree(nodes, 0); // 创建二叉树List<Integer> result = solution.preorderTraversal(root); // 进行非递归前序遍历for (int val : result) { // 输出遍历结果System.out.print(val + " ");}System.out.println();solution.destroyTree(root); // 销毁二叉树}
}
Python
# 二叉树节点的定义
class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = None# 非递归前序遍历
def preorderTraversal(root):result = [] # 存储遍历结果的数组if not root:return result # 如果根节点为空,直接返回空数组stack = [] # 辅助栈,用于存储遍历过程中的节点stack.append(root) # 将根节点入栈while stack: # 当栈非空时循环执行以下操作node = stack.pop() # 获取栈顶节点result.append(node.val) # 将节点值加入结果数组if node.right: # 如果节点有右子节点,将右子节点入栈stack.append(node.right)if node.left: # 如果节点有左子节点,将左子节点入栈stack.append(node.left)return result # 返回结果数组# 创建二叉树
def createTree(nodes, index):if index >= len(nodes) or nodes[index] == -1:return None # 如果节点为空,则返回Noneroot = TreeNode(nodes[index]) # 创建当前节点root.left = createTree(nodes, 2 * index + 1) # 创建左子树root.right = createTree(nodes, 2 * index + 2) # 创建右子树return root # 返回当前节点# 销毁二叉树
def destroyTree(root):if not root:return # 如果根节点为空,直接返回destroyTree(root.left) # 递归销毁左子树destroyTree(root.right) # 递归销毁右子树# 主函数
if __name__ == "__main__":nodes = [1, 2, 3, -1, -1, 4, 5] # 定义二叉树的先序遍历序列root = createTree(nodes, 0) # 创建二叉树result = preorderTraversal(root) # 进行非递归前序遍历print(result) # 输出遍历结果destroyTree(root) # 销毁二叉树