当前位置:网站首页>二叉树的四种遍历方式以及中序后序、前序中序、前序后序、层序创建二叉树【专为力扣刷题而打造】
二叉树的四种遍历方式以及中序后序、前序中序、前序后序、层序创建二叉树【专为力扣刷题而打造】
2022-07-04 19:05:00 【@了凡】
博主介绍:
– 我是了 凡 微信公众号【了凡银河系】期待你的关注。未来大家一起加油啊~
前言
这里三种遍历方式不用过多介绍,相信学过数据结构的人都可以轻松使用递归方式进行遍历,非递归方式思想也是一致的。
根据前序中序、中序后序、前序后序均参考力扣题解所写,只有层序遍历是为了再力扣解题不方便所以才选择在本地解题,但是本地解题不能进行测试,使用其他三种创建方式又过于麻烦,所以想使用层序创建二叉树,思维比较简单供大家参考,有问题可以及时讨论。
前序遍历
由于是前序遍历所以根节点一定在前,遍历顺序为(根、左、右)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 前序遍历
func preorderTraversal(root *TreeNode) []int {
nums := make([]int, 0)
var dfs func(node *TreeNode)
dfs = func(node *TreeNode) {
if node != nil {
nums = append(nums, node.Val) // 根
dfs(node.Left) // 左
dfs(node.Right) // 右
}
}
dfs(root)
return nums
}
中序遍历
由于是中序遍历所以根节点一定在中间,遍历顺序为(左、根、右)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 中序遍历
func inorderTraversal(root *TreeNode) []int {
nums := make([]int, 0)
var dfs func(node *TreeNode)
dfs = func(node *TreeNode) {
if node != nil {
dfs(node.Left) // 左
nums = append(nums, node.Val) // 根
dfs(node.Right) // 右
}
}
dfs(root)
return nums
}
后序遍历
由于是后序遍历所以根节点一定在后面,遍历顺序为(左、右、根)
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 后续遍历
func postorderTraversal(root *TreeNode) []int {
nums := make([]int, 0)
var dfs func(node *TreeNode)
dfs = func(node *TreeNode) {
if node != nil {
dfs(node.Left)
dfs(node.Right)
nums = append(nums, node.Val)
}
}
dfs(root)
return nums
}
层序遍历
层序遍历肯定是一行一行的遍历,其思想就是BFS(像一滴水滴进水潭里的波纹一样一层一层的),这里使用队列不断的暂存下一个子孩子当作下一次的根节点进行遍历它的子孩子。
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 层序遍历
func levelOrder(root *TreeNode) [][]int {
ret := [][]int{
}
if root == nil {
return ret
}
q := []*TreeNode{
root}
for i := 0; len(q) > 0; i++ {
ret = append(ret, []int{
})
p := []*TreeNode{
}
for j := 0; j < len(q); j++ {
node := q[j]
ret[i] = append(ret[i], node.Val)
if node.Left != nil {
p = append(p, node.Left)
}
if node.Right != nil {
p = append(p, node.Right)
}
}
q = p
}
return ret
}
层序创建二叉树
到了重点时刻了,以参考层序遍历为相反思维,首先对一维数组进行拆分成每一层节点,做出二维数组,之后根据遍历每一个孩子当作当前的根节点添加的它的左右孩子。此写法较为丑陋且性能较低,望耐心扣底。这里-1代表空值
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 层序创建二叉树
func sequenceCreation(nums []int) *TreeNode {
if len(nums) == 0 {
return nil
}
if len(nums) == 1 {
return &TreeNode{
nums[0], nil, nil}
}
// 先对数组进行分层分割
sliNums := make([][]int, 0)
count := 1
for i := 0; i < len(nums); {
cont := make([]int, 0)
j := i
for ; j < i+count; j++ {
cont = append(cont, nums[j])
}
i = j
sliNums = append(sliNums, cont)
count *= 2
}
root := new(TreeNode)
root.Val = sliNums[0][0]
queue := []*TreeNode{
root}
count = 0
for i := 1; i < len(sliNums); i++ {
for j := 0; j < len(sliNums[i]); j += 2 {
if sliNums[i][j] != -1 {
queue[count].Left = &TreeNode{
Val: sliNums[i][j]}
queue = append(queue, queue[count].Left)
} else {
if queue[count] != nil {
queue[count].Left = nil
queue = append(queue, queue[count].Left)
}
}
if sliNums[i][j+1] != -1 {
queue[count].Right = &TreeNode{
Val: sliNums[i][j+1]}
queue = append(queue, queue[count].Right)
} else {
if queue[count] != nil {
queue[count].Right = nil
queue = append(queue, queue[count].Right)
}
}
count++
}
}
return root
}
使用案例
这里以力扣的简单题为例:104. 二叉树的最大深度
代码实现
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
return max(maxDepth(root.Left), maxDepth(root.Right)) + 1
}
func main() {
nums := []int{
3, 9, 20, -1, -1, 15, 7}
root := sequenceCreation(nums) // 这个函数就是上述的层序遍历,在这里就不重复粘贴了
fmt.Println(maxDepth(root))
}
测试结果
结果正确
前序中序创建二叉树
这里参考力扣题解,思维比较简单,preorder切片的开始都是根节点,然后和inorder切片进行比较就可以找到左右孩子,不断向下重复比对就可以进行创建完成。
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 前序找根节点,中序找左右分界线
func pIBuildTree(preorder []int, inorder []int) *TreeNode {
if len(preorder) == 0 {
return nil
}
root := &TreeNode{
preorder[0], nil, nil}
i := 0
for ; i < len(inorder); i++ {
if inorder[i] == preorder[0] {
break
}
}
root.Left = pIBuildTree(preorder[1:len(inorder[:i])+1], inorder[:i])
root.Right = pIBuildTree(preorder[len(inorder[:i])+1:], inorder[i+1:])
return root
}
中序后序创建二叉树
和前序中序基本一致,只是这次是中序和后序比对
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 从中序后续创建二叉树
func iPBuildTree(inorder []int, postorder []int) *TreeNode {
idxMap := map[int]int{
}
for i, v := range inorder {
idxMap[v] = i
}
var build func(int, int) *TreeNode
build = func(inorderLeft, inorderRight int) *TreeNode {
// 无剩余节点
if inorderLeft > inorderRight {
return nil
}
// 后序遍历的末尾元素即为当前子树的根节点
val := postorder[len(postorder)-1]
postorder = postorder[:len(postorder)-1]
root := &TreeNode{
Val: val}
// 根据 val 在中序遍历的位置,将中序遍历划分成左右两颗子树
// 由于我们每次都从后序遍历的末尾取元素,所以要先遍历右子树再遍历左子树
inorderRootIndex := idxMap[val]
root.Right = build(inorderRootIndex+1, inorderRight)
root.Left = build(inorderLeft, inorderRootIndex-1)
return root
}
return build(0, len(inorder)-1)
}
前序后序创建二叉树
这里结果可能不唯一
type TreeNode struct {
Val int
Left *TreeNode
Right *TreeNode
}
// 根据前序后续构建二叉树
func constructFromPrePost(preorder []int, postorder []int) *TreeNode {
// 递归结束条件
if len(preorder) == 0 {
return nil
}
// 只有一个元素时,为叶子节点。这一步在889不可省略
if len(preorder) == 1 {
return &TreeNode{
Val: preorder[0]}
}
// 根节点
root := &TreeNode{
Val: preorder[0]}
// 在后序序列中寻找和前序序列根节点下一个节点相等的位置
for pos, node := range postorder {
if node == preorder[1] {
// 构建左子树
root.Left = constructFromPrePost(preorder[1:pos+2], postorder[:pos+1])
// 构建右子树
root.Right = constructFromPrePost(preorder[pos+2:], postorder[pos+1:len(postorder)-1])
break
}
}
return root
}
参考链接:
- 从中序与后序遍历序列构造二叉树:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/solution/cong-zhong-xu-yu-hou-xu-bian-li-xu-lie-gou-zao-14/
- 根据前序和后序遍历构造二叉树:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-postorder-traversal/solution/889-gen-ju-qian-xu-he-hou-xu-bian-li-gou-zw0i/
- 从前序与中序遍历序列构造二叉树:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/cong-qian-xu-yu-zhong-xu-bian-li-xu-lie-gou-zao-9/
创作不易,点个赞吧!
如果需要后续再看点个收藏!
如果对我的文章有兴趣给个关注!
如果有问题,可以关注公众号【了凡银河系】点击联系我私聊。
边栏推荐
- Offset function and windowing function
- FS8B711S14电动红酒开瓶器单片机IC方案开发专用集成IC
- 最长的可整合子数组的长度
- 长城证券开户安全吗 股票开户流程网上开户
- Why is the maximum speed the speed of light
- Stack: how to realize the judgment of valid brackets?
- Lingyun going to sea | 10 jump &huawei cloud: jointly help Africa's inclusive financial services
- LeetCode 871. 最低加油次数
- Flet教程之 05 OutlinedButton基础入门(教程含源码)
- 1500万员工轻松管理,云原生数据库GaussDB让HR办公更高效
猜你喜欢
YOLOv5s-ShuffleNetV2
The company needs to be monitored. How do ZABBIX and Prometheus choose? That's the right choice!
应用实践 | 蜀海供应链基于 Apache Doris 的数据中台建设
Chrome development tool: what the hell is vmxxx file
What is the application technology of neural network and Internet of things
Employment prospects of neural network Internet of things application technology [welcome to add]
[ismb2022 tutorial] the picture shows the precision medicine of learning. Marinka zitnik, Harvard University, keynote speaker, with 87 ppt
HMM hidden Markov model and code implementation
C language - Introduction - Foundation - grammar - process control (VII)
Related concepts of federal learning and motivation (1)
随机推荐
Form组件常用校验规则-1(持续更新中~)
什么叫内卷?
go笔记(1)go语言介绍以及特点
长城证券开户安全吗 股票开户流程网上开户
Is it necessary to apply for code signing certificate for software client digital signature?
【历史上的今天】7 月 4 日:第一本电子书问世;磁条卡的发明者出生;掌上电脑先驱诞生
Understand the reading, writing and creation of files in go language
精选综述 | 用于白内障分级/分类的机器学习技术
Aiming at the "amnesia" of deep learning, scientists proposed that based on similarity weighted interleaved learning, they can board PNAS
How to adapt your games to different sizes of mobile screen
强化学习-学习笔记2 | 价值学习
Decryption function calculates "task state and lifecycle management" of asynchronous task capability
Crystal optoelectronics: ar-hud products of Chang'an dark blue sl03 are supplied by the company
go语言笔记(2)go一些简单运用
Actual combat simulation │ JWT login authentication
为什么最大速度是光速
Practical examples of node strong cache and negotiation cache
Optimize if code with policy mode [policy mode]
go笔记(3)Go语言fmt包的用法
The problem of the maximum difference between the left and right maxima