前言
本文展示LeetCode中与二叉树深度优先遍历相关的三道题,读者可以用来借此默写以检验是否熟悉相关算法,其难度为简单,但是我们推荐读者使用进阶版等更难的实现方法。
LeetCode题目 | 相关题目类型 | 相关链接 |
144 | 二叉树的先序遍历 | https://leetcode-cn.com/problems/binary-tree-preorder-traversal/ |
94 | 二叉树的中序遍历 | https://leetcode-cn.com/problems/binary-tree-inorder-traversal/ |
145 | 二叉树的后序遍历 | https://leetcode-cn.com/problems/binary-tree-postorder-traversal/ |
一、相关API
在实现算法前,如果你对C++/Python的基础API不太熟悉,最好参考下本节内容。
1、C++的API
C++中借助STL实现动态数组、栈、队列时需要调用如下头文件:
#include<cstdlib> /#include<stdlib.h> #include<queue> #include <stack> #include <queue>
C++中借助STL实现动态数组、栈、队列功能的函数对比:
类别 | 数组功能 | 栈功能 | 队列功能 |
创建对象 | vector<Type> M | stack<Type> M | queue<Type> M |
查看当前是否为空 | M.empty() | ||
查看现有元素个数 | M.size() | ||
向容器中添加元素 | M.push_back() | M.push() | M.push() |
获取容器取出元素 | (获取)M.top() (删除)M.pop() | (获取)M.front() (删除)M.pop() | |
容器元素反向 | reverse(result.begin(), result.end()); |
以上需要注意的是出栈和出队操作是分两步,需要先获取后删除,Python中可以直接获取该元素并且删除。
2、Python的API
Python中借助Python List类型实现动态数组、栈、队列功能的函数对比:
类别 | 数组功能 | 栈功能 | 队列功能 |
创建对象 | M = [] | M = [] | M = [] |
查看当前是否为空 | M(可直接使用if判断是否存在) | ||
查看现有元素个数 | len(M) | ||
向容器中添加元素 | M.append() | M.append() | M.append() |
获取容器取出元素 | (默认取出最后一个)M.pop() | (需要指定取出第一个)M.pop(0) | |
容器元素反向 | result[::-1] |
二、算法流程
如果读者对算法流程不是十分清楚,可以参考如下伪代码:
算法类型 | 伪代码流程 |
递归实现(先序为例) | 注意:result要设置为全局类型 result 递归函数(node): 若node为空,返回result;(终止条件) 将node的值加入result;(处理节点值) 递归函数(node.left); 递归函数(node.right)。 返回result。 |
先序遍历 | input:node output:result 初始化结果列表result; 初始化栈stack; 将输入节点node入栈; 当栈stack不为空时: 取出一个栈顶元素命名为cur,将其加入result;(处理节点值) 如果 cur的右子树非空,将右子树入栈; 如果 cur的左子树非空,将左子树入栈。 返回result |
中序遍历 | input:node output:result 初始化结果列表result; 初始化栈stack; 将输入节点node设置为指示节点变量cur; 当cur存在或者栈stack不为空时: 如果cur存在: 将cur入栈stack; 更新cur为cur的左节点; 如果cur不存在: 取出一个栈顶元素命名为cur,将其加入result;(处理节点值) 更新cur为cur的右节点。 |
后序遍历 | input:node output:result 初始化结果列表result; 初始化栈stack, 将输入节点node入栈; 当栈stack不为空时: 取出一个栈顶元素命名为cur,将其加入result;(处理节点值) 如果 cur的右子树非空,将右子树入栈; 如果 cur的左子树非空,将左子树入栈; 反向result; 返回result。 |
层次遍历 | input:node output:result 初始化结果列表result; 初始化队列queue; 将输入节点node入队; 当队列queue不为空时: 取出一个队列元素命名为cur,将其加入result;(处理节点值) 如果 cur的左子树非空,将左子树加入队列; 如果 cur的右子树非空,将右子树加入队列。 返回result |
如果读者对算法流程难以理解,可以记忆如下顺口溜:
先序遍历先入栈,栈不为空就遍历;
出栈一定要处理,先右后左慢入栈;
中序遍历不先入,指示与栈全不空;
存在入栈换左边,不存取栈换右边;
后序遍历同先序,先左后右记反向;
层次遍历同先序,借用队列先左右。
三、相关代码
我们的代码将直接放到同一份代码中,相信读者可非常容易地拆分出各个题目的答案。
1、递归算法(简单版)
Python3版本
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
result = []
def preorderTraversal(self, root: TreeNode) :
if root==None:
return
self.result.append(root.val)
self.preorderTraversal(root.left)
self.preorderTraversal(root.right)
def inorderTraversal(self, root: TreeNode) :
if root==None:
return
self.inorderTraversal(root.left)
self.result.append(root.val)
self.inorderTraversal(root.right)
def postorderTraversal(self, root: TreeNode):
if root==None:
return
self.postorderTraversal(root.left)
self.postorderTraversal(root.right)
self.result.append(root.val)
C++版本
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
vector<int> result;
public:
vector<int> preorderTraversal(TreeNode* root) {
if(root==NULL){
return result;
}
result.push_back(root->val);
preorderTraversal(root->left);
preorderTraversal(root->right);
return result;
}
public:
vector<int> inorderTraversal(TreeNode* root) {
if(root==NULL){
return result;
}
inorderTraversal(root->left);
result.push_back(root->val);
inorderTraversal(root->right);
return result;
}
public:
vector<int> postorderTraversal(TreeNode* root) {
if(root==NULL){
return result;
}
postorderTraversal(root->left);
postorderTraversal(root->right);
result.push_back(root->val);
return result;
}
};
2、递归算法(进阶版)
Python3版本
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
result = []
if root==None:
return result
stack = [root]
while len(stack)>0:
cur = stack.pop()
result.append(cur.val)
if cur.right:
stack.append(cur.right)
if cur.left:
stack.append(cur.left)
return result
def inorderTraversal(self, root: TreeNode) -> List[int]:
result = []
if root==None:
return result;
stack = []
cur = root
while cur or len(stack)>0:
if cur:
stack.append(cur)
cur = cur.right
else:
cur = stack.pop()
result.append(cur.val)
cur = cur.left
def postorderTraversal(self, root: TreeNode) -> List[int]:
result = []
if root==None:
return result
stack = [root]
while len(stack)>0:
cur = stack.pop()
result.append(cur.val)
if cur.left:
stack.append(cur.left)
if cur.right:
stack.append(cur.right)
result = result[::-1]
return result
C++版本
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> result;
if(root==NULL){
return result;
}
stack<TreeNode*> stack;
stack.push(root);
while(!stack.empty()){
TreeNode* cur = stack.top();
stack.pop();
result.push_back(cur->val);
if(cur->right){
stack.push(cur->right);
}
if(cur->left){
stack.push(cur->left);
}
}
return result;
}
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> result;
if(root==NULL){
return result;
}
stack<TreeNode*> stack;
TreeNode* cur = root;
while(cur!=NULL||!stack.empty()){
if(cur!=NULL){
stack.push(cur);
cur = cur->left;
}
else{
cur = stack.top();
stack.pop();
result.push_back(cur->val);
cur = cur->right;
}
}
return result;
}
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
if(root==NULL){
return result;
}
stack<TreeNode*> stack;
stack.push(root);
while(!stack.empty()){
TreeNode* cur = stack.top();
stack.pop();
result.push_back(cur->val);
if(cur->left){
stack.push(cur->left);
}
if(cur->right){
stack.push(cur->right);
}
}
reverse(result.begin(), result.end());
return result;
}
};