【LeeCode 面试题】二叉树的前序遍历,中序遍历,后序遍历递归和迭代的两种实现方式
时间:2022-07-23
本文章向大家介绍【LeeCode 面试题】二叉树的前序遍历,中序遍历,后序遍历递归和迭代的两种实现方式,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
二叉树类型的题目是LeeCode中常见的题型
- 能够结合队列、栈、链表、字符串等多种数据结构;
- 需要掌握树、图的遍历方式;
- 需要掌握递归函数的使用,并自己设计具体过程;
- 实际工程中也会经常遇到。
树的常见遍历有先序遍历、中序遍历、后序遍历三种:
- 先序遍历:根、左、右
- 中序遍历:左、根、右
- 后序遍历:左、右、根
今天我们就介绍下树的基本遍历用Python的递归和迭代的两种实现方式
递归实现
使用递归来实现三种遍历方式是比较容易的,只要改变根结点的打印顺序就可以了
"""
示例二叉树
1
2
/
3
"""
from typing import List
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 先序遍历
def preorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
def pT(node):
if not node:
return
ret.append(node.val)
pT(node.left)
pT(node.right)
pT(root)
return ret
# 中序遍历
def inorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
def pT(node):
if not node:
return
pT(node.left)
ret.append(node.val)
pT(node.right)
pT(root)
return ret
# 后序遍历
def postorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
def pT(node):
if not node:
return
pT(node.left)
pT(node.right)
ret.append(node.val)
pT(root)
return ret
if __name__ == "__main__":
t2 = TreeNode(2)
t2.left = TreeNode(3)
t = TreeNode(1)
t.right = t2
s = Solution()
ret = s.preorderTraversal(t)
print("先序遍历", ret)
ret = s.inorderTraversal(t)
print("中序遍历", ret)
ret = s.postorderTraversal(t)
print("后序遍历", ret)
执行结果
>> 先序遍历 [1, 2, 3]
>> 中序遍历 [2, 1, 3]
>> 后序遍历 [2, 3, 1]
迭代实现
先序遍历
具体过程:
- 首先申请一个新的栈,记为stack;
- 然后将头节点head压入stack中;
- 每次从stack中弹出栈顶节点,记为cur,然后打印cur节点的值。如果cur右孩子不为空的话,将cur的有孩子先压入stack中;最后如果cur的左孩子不为空的话,将cur的左孩子压入stack中;
- 不断重复步骤3,直到stack为空,全部过程结束。
from typing import List
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
ret = []
stack = []
cur = root
while stack or cur:
while cur:
stack.append(cur)
ret.append(cur.val)
cur = cur.left
cur = stack.pop()
cur = cur.right
return ret
if __name__ == "__main__":
t2 = TreeNode(2)
t2.left = TreeNode(3)
t = TreeNode(1)
t.right = t2
s = Solution()
ret = s.preorderTraversal(t)
print(ret)
中序遍历
具体过程:
- 首先申请一个新的栈,记为stack,申请一个变量cur,cur初始化为头节点;
- 先把cur节点压入栈中,对以cur节点为头的整棵子树来说,依次把整棵树的左边界压入栈中,即不断令cur=cur.left,然后重复步骤2;
- 不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点,记为node;打印node的值,并让cur=node.right,然后继续重复步骤2;
- 当stack为空并且cur为空时,全部过程结束。
from typing import List
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
ret = []
stack = []
cur = root
while stack or cur:
while cur:
stack.append(cur)
cur = cur.left
node = stack.pop()
ret.append(node.val)
cur = node.right
return ret
if __name__ == "__main__":
t2 = TreeNode(2)
t2.left = TreeNode(3)
t = TreeNode(1)
t.right = t2
s = Solution()
ret = s.inorderTraversal(t)
print(ret)
后序遍历
具体过程:
- 首先申请两个栈,记为分别s1、s2;
- 然后将头节点head压入s1中;
- 从s1中弹出的节点记为cur,然后先把cur的左孩子压入s1中,然后把cur1的右孩子压入s1中;
- 在整个过程中,每一个从s1中弹出的节点都放进s2中;
- 不断重复步骤3和步骤4,直到s1为空,过程停止;
- 从s2中依次弹出节点并打印,打印的顺序就是后序遍历的顺序了。
from typing import List
# Definition for a binary tree node.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
def preorderTraversal(self, root: TreeNode) -> List[int]:
if not root:
return []
s1 = [root]
s2 = []
while s1:
node = s1.pop()
s2.append(node.val)
if node.left:
s1.append(node.left)
if node.right:
s1.append(node.right)
s2.reverse()
return s2
if __name__ == "__main__":
t2 = TreeNode(2)
t2.left = TreeNode(3)
t = TreeNode(1)
t.right = t2
s = Solution()
ret = s.preorderTraversal(t)
print(ret)end
- MySQL中的半同步复制(r11笔记第65天)
- Linux系统LVM逻辑卷创建过程以及自动化脚本
- 一个闪回区报警的数据恢复(r11笔记第62天)
- 利用腾讯云COS云对象存储定时远程备份网站
- 分享一个自写的Python远程命令和文件(夹)传输类
- Oracle数据误操作全面恢复实战(r11笔记第78天)
- 远程协助解决异常宕库的问题(r11笔记第75天)
- Nginx-helper纯代码版,文章评论发布自动清理Fastcgi缓存
- MySQL和Oracle行值表达式对比(r11笔记第74天)
- 闪回数据库不是“万金油”(r11笔记第73天)
- 修改Apache的超时设置,解决长连接请求超时问题
- Oracle 12cR2初体验(r11笔记第91天)
- MySQL中的undo截断(r11笔记第89天)
- Linux系统 df 命令显示异常、分区丢失问题解决
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- android如何获取联系人所有信息
- Android条目拖拽删除功能实例代码
- Android Button点击事件的四种实现方法
- Android的App启动时白屏的问题解决办法
- Android获取本机各种类型文件的方法
- Android保存联系人到通讯录的方法
- Android学习之本地广播使用方法详解
- Android编程获取图片数据的方法详解
- Android垂直滚动控件ScrollView使用方法详解
- Android开发之自定义view实现通讯录列表A~Z字母提示效果【附demo源码下载】
- Android ExpandableRecyclerView使用方法详解
- Android开发之SD卡文件操作分析
- Android学习之Broadcast的简单使用
- Android 仿微信自定义数字键盘的实现代码
- RN在Android打包发布App(详解)