go语言|数据结构:二叉树(2)广度和深度搜索_数据结构广度和深度怎么导入

import “fmt”

type btNode struct {
Data interface{}
Lchild, Rchild *btNode
}

type biTree struct {
root *btNode
}

func Create(data interface{}) *biTree {
var list []interface{}
btree := &biTree{}
switch data.(type) {
case []interface{}:
list = append(list, data.([]interface{})…)
default:
list = append(list, data)
}
if len(list) > 0 {
btree.root = &btNode{Data: list[0]}
for _, data := range list[1:] {
btree.AppendNode(data)
}
}
return btree
}

func (bt *biTree) Append(data interface{}) {
var list []interface{}
switch data.(type) {
case []interface{}:
list = append(list, data.([]interface{})…)
default:
list = append(list, data)
}
if len(list) > 0 {
for _, data := range list {
bt.AppendNode(data)
}
}
}

func (bt *biTree) AppendNode(data interface{}) {
root := bt.root
if root == nil {
bt.root = &btNode{Data: data}
return
}
Queue := []*btNode{root}
for len(Queue) > 0 {
cur := Queue[0]
Queue = Queue[1:]
if cur.Lchild != nil {
Queue = append(Queue, cur.Lchild)
} else {
cur.Lchild = &btNode{Data: data}
return
}
if cur.Rchild != nil {
Queue = append(Queue, cur.Rchild)
} else {
cur.Rchild = &btNode{Data: data}
break
}
}
}

func (bt *biTree) Levelorder() []interface{} {
var res []interface{}
root := bt.root
if root == nil {
return res
}
Queue := []*btNode{root}
for len(Queue) > 0 {
cur := Queue[0]
Queue = Queue[1:]
res = append(res, cur.Data)
if cur.Lchild != nil {
Queue = append(Queue, cur.Lchild)
}
if cur.Rchild != nil {
Queue = append(Queue, cur.Rchild)
}
}
return res
}

func (bt *biTree) Preorder() []interface{} {
var res []interface{}
cur := bt.root
Stack := []*btNode{}
for cur != nil || len(Stack) > 0 {
for cur != nil {
res = append(res, cur.Data)
Stack = append(Stack, cur)
cur = cur.Lchild
}
if len(Stack) > 0 {
cur = Stack[len(Stack)-1]
Stack = Stack[:len(Stack)-1]
cur = cur.Rchild
}
}
return res
}

func (bt *biTree) Inorder() []interface{} {
var res []interface{}
cur := bt.root
Stack := []*btNode{}
for cur != nil || len(Stack) > 0 {
for cur != nil {
Stack = append(Stack, cur)
cur = cur.Lchild
}
if len(Stack) > 0 {
cur = Stack[len(Stack)-1]
res = append(res, cur.Data)
Stack = Stack[:len(Stack)-1]
cur = cur.Rchild
}
}
return res
}

func (bt *biTree) Postorder() []interface{} {
var res []interface{}
var cur, pre *btNode
Stack := []*btNode{bt.root}
for len(Stack) > 0 {
cur = Stack[len(Stack)-1]
if cur.Lchild == nil && cur.Rchild == nil ||
pre != nil && (pre == cur.Lchild || pre == cur.Rchild) {
res = append(res, cur.Data)
Stack = Stack[:len(Stack)-1]
pre = cur
} else {
if cur.Rchild != nil {
Stack = append(Stack, cur.Rchild)
}
if cur.Lchild != nil {
Stack = append(Stack, cur.Lchild)
}
}
}
return res
}

func main() {

list := []interface{}{1, 2, 3, 4, 5, 6, 7}

tree := &biTree{}
fmt.Println(tree.Preorder())
tree.Append(0)
fmt.Println(tree.Preorder())
tree.Append(1)
fmt.Println(tree.Preorder())

tree = Create(list)
fmt.Println(tree.Preorder())
fmt.Println(tree.Inorder())
fmt.Println(tree.Postorder())

tree.Append("+")
tree.Append("-")
fmt.Println(tree.Inorder())
tree.Append([]interface{}{"A", "B", "C"})
fmt.Println(tree.Preorder())
fmt.Println(tree.Inorder())
fmt.Println(tree.Postorder())

}

/*
[]
[0]
[0 1]
[1 2 4 5 3 6 7]
[4 2 5 1 6 3 7]
[4 5 2 6 7 3 1]
[+ 4 - 2 5 1 6 3 7]
[1 2 4 + - 5 A B 3 6 C 7]
[+ 4 - 2 A 5 B 1 C 6 3 7]
[+ - 4 A B 5 2 C 6 7 3 1]
*/


### 自定义包 biTree


上面的代码中,去掉import "fmt"一行 及 main()函数全部,package main替换成 package biTree,然后另存为 biTree.go。


接下来在DOS窗口用set gopath查看GOPATH变量,我的电脑返回:



> 
> C:\Users\admin>set gopath
> 
> 
> GOPATH=C:\Users\admin\go;d:\GOsrc
> 
> 
> 


在gopath的任一路径下新建一个src文件夹,再在src下新建biTree文件夹,最后把biTree.go存放到此文件夹下,就能导入import使用了。


注意:**自定义包中的函数和方法命名时一定要首字母大写**,否则调用会无法找到。


#### 导入和调用



package main

import (
“biTree” //导入二叉树自定义包 biTree
“fmt”
)

func main() {

list := []interface{}{1, 2, 3, 4, 5, 6, 7}

tree := biTree.Create(list)  //调用自定义包中的函数,需要用“包名称.”作前缀
fmt.Println(tree.Preorder()) //调用方法则不需要前缀,tree就是此包定义的对象
fmt.Println(tree.Inorder())
fmt.Println(tree.Postorder())
fmt.Println(tree.Levelorder())

tree.Append(0)
tree.Append("+")
tree.Append("-")
fmt.Println(tree.Inorder())
tree.Append([]interface{}{"A", "B", "C"})
fmt.Println(tree.Preorder())
fmt.Println(tree.Inorder())
fmt.Println(tree.Postorder())
fmt.Println(tree.Levelorder())

}

/*
[1 2 4 5 3 6 7]
[4 2 5 1 6 3 7]
[4 5 2 6 7 3 1]
[1 2 3 4 5 6 7]
[0 4 + 2 - 5 1 6 3 7]
[1 2 4 0 + 5 - A 3 6 B C 7]
[0 4 + 2 - 5 A 1 B 6 C 3 7]
[0 + 4 - A 5 2 B C 6 7 3 1]
[1 2 3 4 5 6 7 0 + - A B C]
*/


### 广度优先搜索BFS & 深度优先搜索DFS


是连通图等图结构的一种遍历算法原型,而树也可以看作是一种没用环的特殊图结构。


#### 广度优先搜索BFS


Breath First Search,也称宽度优先搜索,缩写BFS。也即先横向再纵向的搜索,BFS使用**队列**来实现。BFS就是上一集中写的层序遍历Levelorder(),层序遍历即广度优先。


![](https://img-blog.csdnimg.cn/c45664b2b0b34a2ca10875ebd99c2e2c.gif)


#### 深度优先搜索DFS


Depth First Search,缩写DFS。也即先纵向再横向的搜索,DFS使用**栈**来实现。DFS就是上一集中写的先序遍历Preorder(),可认为先序遍历即深度优先。


![](https://img-blog.csdnimg.cn/c59197aa8fa247b3a47b0cf4d17719a5.gif)


#### 遍历二叉树全部叶子结点


**递归法:**



func (bt *btNode) leaves() []interface{} {
var res []interface{}
if bt != nil {
if bt.Lchild == nil && bt.Rchild == nil {
res = append(res, bt.Data)
}
res = append(res, bt.Lchild.leaves()…)
res = append(res, bt.Rchild.leaves()…)
}
return res
}


**广度优先BFS:**



func (bt *biTree) LeafNodeBFS() []interface{} {
var res []interface{}
root := bt.root
if root == nil {
return res
}
Queue := []*btNode{root}
for len(Queue) > 0 {
cur := Queue[0]
Queue = Queue[1:]
if cur.Lchild == nil && cur.Rchild == nil {
res = append(res, cur.Data)
}
if cur.Lchild != nil {
Queue = append(Queue, cur.Lchild)
}
if cur.Rchild != nil {
Queue = append(Queue, cur.Rchild)
}
}
return res
}


**深度优先DFS:**



func (bt *biTree) LeafNodeDFS() []interface{} {
var res []interface{}
cur := bt.root
Stack := []*btNode{}
for cur != nil || len(Stack) > 0 {
for cur != nil {
if cur.Lchild == nil && cur.Rchild == nil {
res = append(res, cur.Data)
}
Stack = append(Stack, cur)
cur = cur.Lchild
}
if len(Stack) > 0 {
cur = Stack[len(Stack)-1]
Stack = Stack[:len(Stack)-1]
cur = cur.Rchild
}
}
return res
}




---


### **BFS/DFS题目实例**


#### **实例1:层序遍历二叉树成二维数组**



> 
> **(leetcode102#) Binary Tree Level Order Traversal**
> 
> 
> Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).  
>  For Example:  
>  Given binary tree [3,9,20,null,null,15,7],  
>   3  
>   / \  
>  9 20  
>      / \  
>    15 7
> 
> 
> return its level order traversal as:  
>  [  
>  [3],  
>  [9,20],  
>  [15,7]  
>  ]
> 
> 
> 
> **(leetcode107#) Binary Tree Level Order Traversal II**
> 
> 
> 102题的结果倒序,返回[[3],[9,20],[15,7]],代码略。
> 
> 
> 


遍历代码如下,把它写进biTree.go备用:



func (bt *biTree) BForder2D() [][]interface{} {
var res [][]interface{}
root := bt.root
if root == nil {
return res
}
Queue := []*btNode{root}
for len(Queue) > 0 {
Nodes := []interface{}{}
Levels := len(Queue)
for Levels > 0 {
cur := Queue[0]
Queue = Queue[1:]
Nodes = append(Nodes, cur.Data)
Levels–
if cur.Lchild != nil {
Queue = append(Queue, cur.Lchild)
}
if cur.Rchild != nil {
Queue = append(Queue, cur.Rchild)
}
}
res = append(res, Nodes)
}
return res
}


遍历过程如以下动图:


![](https://i-blog.csdnimg.cn/blog_migrate/271300dee27526635b0d67e126644017.gif)


测试代码:





![img](https://img-blog.csdnimg.cn/img_convert/8a4e23d8a9c2926cb11bb5ea9316e97a.png)
![img](https://img-blog.csdnimg.cn/img_convert/ba2e837e9b556d1143f3d0a04888a742.png)
![img](https://img-blog.csdnimg.cn/img_convert/577ab3e47363833dd549c0b843c98a70.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

urn res
}

遍历过程如以下动图:

测试代码:

[外链图片转存中…(img-nTrdY9yk-1714701349834)]
[外链图片转存中…(img-COxawGjl-1714701349835)]
[外链图片转存中…(img-HneqIlM9-1714701349835)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值