四、用go语言,对于一棵有 n 个结点的树,请设计在 O(n)时间内完成的先序遍历算法和后序遍历算法。

我个人喜欢灵小智。

文心一言:

在 Go 语言中,我们可以使用递归来实现树的前序遍历和后序遍历。以下是实现这两种方法的代码。

首先,我们定义一个树节点的结构:

typeTreeNodestruct{
Valint
Left*TreeNode
Right*TreeNode
}

接下来,我们实现前序遍历(根-左-右):

funcpreOrderTraversal(root*TreeNode){
ifroot==nil{//空节点则返回
return
}
fmt.Println(root.Val)//先打印根节点
preOrderTraversal(root.Left)//然后遍历左子树
preOrderTraversal(root.Right)//最后遍历右子树
}

然后,我们实现后序遍历(左-右-根):

funcpostOrderTraversal(root*TreeNode){
ifroot==nil{//空节点则返回
return
}
postOrderTraversal(root.Left)//先遍历左子树
postOrderTraversal(root.Right)//然后遍历右子树
fmt.Println(root.Val)//最后打印根节点
}

以上的前序遍历和后序遍历的时间复杂度都是 O(n),其中 n 是树的节点数量。这是因为每个节点都会被访问一次,每个节点只会被访问一次。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

讯飞星火,代码正常运行:

packagemain
import"fmt"
typeTreeNodestruct{
Valint
Left*TreeNode
Right*TreeNode
}
funcpreorderTraversal(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
stack:=[]*TreeNode{root}
res:=[]int{root.Val}
forlen(stack)>0{
node:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
ifnode.Right!=nil{
stack=append(stack,node.Right)
res=append(res,node.Right.Val)
}
ifnode.Left!=nil{
stack=append(stack,node.Left)
res=append(res,node.Left.Val)
}
}
returnres
}
funcpostorderTraversal(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
stack:=[]*TreeNode{root}
res:=[]int{}
forlen(stack)>0{
node:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
res=append(res,node.Val)
ifnode.Left!=nil{
stack=append(stack,node.Left)
}
ifnode.Right!=nil{
stack=append(stack,node.Right)
}
}
fori,n:=0,len(res);ires[i],res[n-1-i]=res[n-1-i],res[i]
}
returnres
}
funcmain(){
root:=&TreeNode{Val:1}
root.Left=&TreeNode{Val:2}
root.Right=&TreeNode{Val:3}
root.Left.Left=&TreeNode{Val:4}
root.Left.Right=&TreeNode{Val:5}
root.Right.Left=&TreeNode{Val:6}
root.Right.Right=&TreeNode{Val:7}
fmt.Println("先序遍历结果:",preorderTraversal(root))
fmt.Println("后序遍历结果:",postorderTraversal(root))
}

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

360智脑,代码不能运行:

以下是用go语言实现一棵有 n 个结点的树的先序遍历和后序遍历算法:

先序遍历算法:

packagemain
import"fmt"
funcpreOrder(node*Node)[]int{
res:=[]int{}
ifnode!=nil{
res=append(res,node.val)
preOrder(node.left)
preOrder(node.right)
}
returnres
}
funcmain(){
//创建一棵有3个结点的二叉树
root:=&Node{val:10,left:nil,right:nil}
root.left=&Node{val:5,left:nil,right:&Node{}}
root.left.left=&Node{val:3,left:nil,right:nil}
root.left.right=&Node{val:7,left:nil,right:nil}
root.right=&Node{val:15,left:nil,right:&Node{}}
root.right.left=&Node{val:2,left:nil,right:nil}
root.right.right=&Node{val:12,left:nil,right:nil}
//输出先序遍历结果
res:=preOrder(root)
fmt.Println(res)//输出[105721215]
}

后序遍历算法:

packagemain
import"fmt"
funcpostOrder(node*Node)[]int{
res:=[]int{}
ifnode!=nil{
res=append(res,node.val)
postOrder(node.left)
postOrder(node.right)
}
returnres
}
funcmain(){
//创建一棵有3个结点的二叉树
root:=&Node{val:10,left:nil,right:nil}
root.left=&Node{val:5,left:nil,right:nil}
root.left.left=&Node{val:3,left:nil,right:nil}
root.left.right=&Node{val:7,left:nil,right:nil}
root.right=&Node{val:15,left:nil,right:nil}
root.right.left=&Node{val:2,left:nil,right:nil}
root.right.right=&Node{val:12,left:nil,right:nil}
//输出后序遍历结果
res:=postOrder(root)
fmt.Println(res)//输出[152127105315]
}

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

智谱清言:

在 Go 语言中,可以使用递归或迭代方法实现树的遍历。以下是先序遍历和后序遍历的递归和迭代算法:

1.先序遍历算法:

递归算法:

funcpreOrderTraversalRecursive(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=[]int{root.Val}
result=append(result,preOrderTraversalRecursive(root.Left)...)
result=append(result,preOrderTraversalRecursive(root.Right)...)
returnresult
}

迭代算法:

funcpreOrderTraversalIterative(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=[]int{}
stack:=[]*TreeNode{root}
forlen(stack)>0{
node:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
result=append(result,node.Val)
ifnode.Right!=nil{
stack=append(stack,node.Right)
}
ifnode.Left!=nil{
stack=append(stack,node.Left)
}
}
returnresult
}

2.后序遍历算法:

递归算法:

funcpostOrderTraversalRecursive(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=postOrderTraversalRecursive(root.Left)
result=append(result,root.Val)
result=append(result,postOrderTraversalRecursive(root.Right)...)
returnresult
}

迭代算法:

funcpostOrderTraversalIterative(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=[]int{}
stack:=[]*TreeNode{root}
forlen(stack)>0{
node:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
result=append(result,node.Val)
ifnode.Left!=nil{
stack=append(stack,node.Left)
}
ifnode.Right!=nil{
stack=append(stack,node.Right)
}
}
//Reversetheresultarraytogetpost-ordertraversal
fori,j:=0,len(result)-1;iresult[i],result[j]=result[j],result[i]
}
returnresult
}

以上算法均能在 O(n) 时间内完成树的遍历。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

通义千问:

这是一个经典的二叉树问题,我们可以使用深度优先搜索(DFS)来解决这个问题。

首先,我们需要定义一个树节点的数据结构:

typeTreeNodestruct{
Valint
Left*TreeNode
Right*TreeNode
}

然后,我们分别实现先序遍历和后序遍历的函数:

先序遍历:根 -> 左 -> 右

funcpreorderTraversal(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=make([]int,0)
stack:=[]*TreeNode{root}
forlen(stack)>0{
node:=stack[len(stack)-1]
result=append(result,node.Val)
ifnode.Right!=nil{
stack=append(stack,node.Right)
}
ifnode.Left!=nil{
stack=append(stack,node.Left)
}else{
stack=stack[:len(stack)-1]
}
}
returnresult
}

后序遍历:左 -> 右 -> 根

funcpostorderTraversal(root*TreeNode)[]int{
ifroot==nil{
return[]int{}
}
result:=make([]int,0)
stack:=[]*TreeNode{root}
prev:=root
forlen(stack)>0{
node:=stack[len(stack)-1]
ifnode.Left==nil&&node.Right==nil||node==prev{
result=append([]int{node.Val},result...)
prev=node
stack=stack[:len(stack)-1]
}elseifnode.Right!=nil{
stack=append(stack,node.Right)
}else{
stack=stack[:len(stack)-1]
ifnode.Left!=nil{
stack=append(stack,node.Left)
}
}
}
returnresult
}

这两种方法的时间复杂度都是O(n),其中n是树中节点的数量,因为我们只需要遍历一次所有的节点。空间复杂度也是O(n),因为在最坏的情况下,我们可能需要将所有的节点都压入栈中。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

天工:

先序遍历算法:

先序遍历是指先访问根节点,然后依次访问左子树和右子树。在 Go 语言中,可以使用递归实现先序遍历算法。具体实现如下:

//定义一个树节点结构体
typeTreeNodestruct{
Valint
Left*TreeNode
Right*TreeNode
}
//先序遍历算法
funcPreorderTraversal(root*TreeNode){
ifroot==nil{
return
}
//访问当前节点
fmt.Printf("%d",root.Val)
//递归访问左右子树
PreorderTraversal(root.Left)
PreorderTraversal(root.Right)
}

后序遍历算法:

后序遍历是指先访问左子树,然后访问右子树,最后访问根节点。在 Go 语言中,可以使用递归实现后序遍历算法。具体实现如下:

//定义一个树节点结构体
typeTreeNodestruct{
Valint
Left*TreeNode
Right*TreeNode
}
//后序遍历算法
funcPostorderTraversal(root*TreeNode){
ifroot==nil{
return
}
//递归访问左右子树
PostorderTraversal(root.Left)
PostorderTraversal(root.Right)
//访问当前节点
fmt.Printf("%d",root.Val)
}

以上两个算法都是使用递归实现的,时间复杂度为 O(n),空间复杂度为 O(h),其中 h 是树的高度。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

灵小智,代码正常运行:

在Go语言中,可以使用递归的方式实现树的先序遍历和后序遍历算法。下面是相应的实现:

packagemain
import"fmt"
//树的节点结构定义
typeTreeNodestruct{
Valint
Children[]*TreeNode
}
//先序遍历函数
funcPreorderTraversal(root*TreeNode){
ifroot==nil{
return
}
fmt.Printf("%d",root.Val)//先输出当前节点的值
for_,child:=rangeroot.Children{
PreorderTraversal(child)//递归遍历子节点
}
}
//后序遍历函数
funcPostorderTraversal(root*TreeNode){
ifroot==nil{
return
}
for_,child:=rangeroot.Children{
PostorderTraversal(child)//递归遍历子节点
}
fmt.Printf("%d",root.Val)//最后输出当前节点的值
}
funcmain(){
//构建一个示例树
root:=&TreeNode{Val:1}
node2:=&TreeNode{Val:2}
node3:=&TreeNode{Val:3}
node4:=&TreeNode{Val:4}
node5:=&TreeNode{Val:5}
root.Children=[]*TreeNode{node2,node3,node4}
node2.Children=[]*TreeNode{node5}
//先序遍历
fmt.Println("PreorderTraversal:")
PreorderTraversal(root)
fmt.Println()
//后序遍历
fmt.Println("PostorderTraversal:")
PostorderTraversal(root)
fmt.Println()
}

以上代码通过先序遍历和后序遍历的方式遍历了一棵示例树,并输出了遍历结果。请注意,这里的先序遍历和后序遍历算法的时间复杂度为 O(n),其中 n 是树中节点的个数。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

chatgpt,代码正常运行:

在Go语言中,可以使用迭代的方式来实现树的先序遍历和后序遍历,以保证时间复杂度为O(n)。以下是示例代码:

packagemain
import(
"fmt"
)
//树节点结构体
typeNodestruct{
Valueint
Left*Node
Right*Node
}
//先序遍历
funcPreorderTraversal(root*Node){
ifroot==nil{
return
}
stack:=[]*Node{root}
forlen(stack)>0{
node:=stack[len(stack)-1]
stack=stack[:len(stack)-1]
fmt.Printf("%d",node.Value)
ifnode.Right!=nil{
stack=append(stack,node.Right)
}
ifnode.Left!=nil{
stack=append(stack,node.Left)
}
}
}
//后序遍历
funcPostorderTraversal(root*Node){
ifroot==nil{
return
}
stack1:=[]*Node{root}
stack2:=[]*Node{}
forlen(stack1)>0{
node:=stack1[len(stack1)-1]
stack1=stack1[:len(stack1)-1]
stack2=append(stack2,node)
//左子树先入栈
ifnode.Left!=nil{
stack1=append(stack1,node.Left)
}
//右子树后入栈
ifnode.Right!=nil{
stack1=append(stack1,node.Right)
}
}
fori:=len(stack2)-1;i>=0;i--{
fmt.Printf("%d",stack2[i].Value)
}
}
funcmain(){
//构建一棵树作为示例
root:=&Node{
Value:1,
Left:&Node{
Value:2,
Left:&Node{
Value:4,
Left:nil,
Right:nil,
},
Right:&Node{
Value:5,
Left:nil,
Right:nil,
},
},
Right:&Node{
Value:3,
Left:&Node{
Value:6,
Left:nil,
Right:nil,
},
Right:nil,
},
}
fmt.Println("先序遍历结果:")
PreorderTraversal(root)
fmt.Println("\n后序遍历结果:")
PostorderTraversal(root)
}

以上代码中,我们使用了两个栈来实现后序遍历。第一个栈用于模拟先序遍历,将右子节点先入栈,然后左子节点入栈。第二个栈用于保存逆向的结果,在第一个栈为空时,将第一个栈中的元素依次弹出并加入到第二个栈中,然后输出即为后序遍历结果。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片