2021-08-14 16:57:30

二叉树的递归和非递归遍历

二叉树的遍历

前序、中序、后序,包括递归版本和非递归版本

完整代码

  • 新建文件
  • 复制粘贴
  • 运行代码

效果截图

  • 测试数据
    image.png
  • 运行结果
    image.png

代码

package main

import "log"

type Node struct {
	Val   int
	Left  *Node
	Right *Node
}

// 测试数据
// 	3
// / \
// 9  20
//  /  \
// 15   7
func main() {
	tree := Node{}
	tree.Val = 3
	tree.Left = &Node{
		Val: 9,
	}
	tree.Right = &Node{
		Val: 20,
		Left: &Node{
			Val: 15,
		},
		Right: &Node{
			Val: 7,
		},
	}
	// ------------------ end
	// 先序遍历递归
	log.Printf("%-10s\t%v", "先序遍历递归", DLRdg(&tree))
	// 先序遍历
	log.Printf("%-10s\t%v", "先序遍历", DLR(&tree))
	// 中序遍历递归
	log.Printf("%-10s\t%v", "中序遍历递归", LDRdg(&tree))
	// 中序遍历
	log.Printf("%-10s\t%v", "中序遍历", LDR(&tree))
	// 后序遍历递归
	log.Printf("%-10s\t%v", "后序遍历递归", LRDdg(&tree))
	// 后序遍历
	log.Printf("%-10s\t%v", "后序遍历", LRD(&tree))
	// 后序遍历-双栈法
	log.Printf("%-10s\t%v", "后序遍历-双栈法", LRD2(&tree))
}

// 先序遍历递归
func DLRdg(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	ret = append(ret, root.Val)
	left := DLRdg(root.Left)
	ret = append(ret, left...)
	right := DLRdg(root.Right)
	ret = append(ret, right...)
	return ret
}

// 先序遍历递归
func DLR(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	stack := make([]*Node, 0, 4)
	for root != nil || len(stack) > 0 {
		for root != nil {
			ret = append(ret, root.Val)
			stack = append(stack, root)
			root = root.Left
		}
		root = stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		root = root.Right
	}
	return ret
}

// 中序遍历递归
func LDRdg(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	left := LDRdg(root.Left)
	ret = append(ret, left...)
	ret = append(ret, root.Val)
	right := LDRdg(root.Right)
	ret = append(ret, right...)
	return ret
}

// 中序遍历
func LDR(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	stack := make([]*Node, 0, 4)
	for root != nil || len(stack) > 0 {
		for root != nil {
			stack = append(stack, root)
			root = root.Left
		}
		root = stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		ret = append(ret, root.Val)
		root = root.Right
	}
	return ret
}

// 后序遍历递归
func LRDdg(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	left := LRDdg(root.Left)
	ret = append(ret, left...)
	right := LRDdg(root.Right)
	ret = append(ret, right...)
	ret = append(ret, root.Val)
	return ret
}

// 后序遍历
func LRD(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	stack := make([]*Node, 0, 4)
	var last *Node
	for root != nil || len(stack) > 0 {
		for root != nil {
			stack = append(stack, root)
			root = root.Left
		}
		peek := stack[len(stack)-1]
		// 当前节点的右节点为空
		// 或者已经访问过了才能访问
		if peek.Right == nil || peek.Right == last {
			stack = stack[:len(stack)-1]
			ret = append(ret, peek.Val)
			last = peek
		} else {
			root = peek.Right
		}
	}
	return ret
}

// 后序遍历-双栈法
func LRD2(root *Node) []int {
	if root == nil {
		return []int{}
	}
	ret := make([]int, 0, 4)
	stack := make([]*Node, 0, 4)
	// 初始化放入根节点
	stack = append(stack, root)
	for len(stack) > 0 {
		root = stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		// // 巧妙的方式实现另外一个栈 v1
		// // 内存分配次数和元素移动次数增加
		// ret = append([]int{root.Val}, ret...)
		// // 巧妙的方式实现另外一个栈 v2
		// // 相对于 v1 减少内存分配次数
		ret = append(ret, root.Val)
		copy(ret[1:], ret[:len(ret)-1])
		ret[0] = root.Val
		if root.Left != nil {
			stack = append(stack, root.Left)
		}
		if root.Right != nil {
			stack = append(stack, root.Right)
		}
	}
	return ret
}


本文链接:https://blog.zxysilent.com/post/tree-dlf-ldf-lfd-visit.html

-- EOF --

Comments