算法-二叉树前中后层遍历

package main

import (
	"container/list"
	"fmt"
)

type Node struct {
	data  any
	left  *Node
	right *Node
}
type Tree struct {
	root *Node
}

// 创建一颗二叉搜索树left < root < right(条件)
func (t *Tree) createTree(root *Node, data interface{}) *Node {

	if root == nil {
		node := &Node{
			data:  data,
			left:  nil,
			right: nil,
		}
		return node
	}
	// 比较时,需要具体的类型
	if data.(int) < root.data.(int) {
		root.left = t.createTree(root.left, data)
	} else {
		root.right = t.createTree(root.right, data)
	}
	return root
}

// 前序遍历
func (t *Tree) QDisplay(root *Node) {
	if root == nil {
		return
	}
	fmt.Println(root.data)
	t.QDisplay(root.left)
	t.QDisplay(root.right)
}

// 非递归前序遍历
func (t *Tree) NoQDisplay(root *Node) {
	if root == nil {
		return
	}
	curr := root
	st := list.New()
	st.PushBack(curr)
	for curr != nil || st.Len() != 0 {
		t := st.Back()
		st.Remove(t)
		m := t.Value.(*Node)
		fmt.Println(m.data)
		if m.right != nil {
			st.PushBack(m.right)
		}
		if m.left != nil {
			st.PushBack(m.left)
		}
	}
}

// 中序遍历
func (t *Tree) ZDisplay(root *Node) {
	if root == nil {
		return
	}
	t.ZDisplay(root.left)
	fmt.Println(root.data)
	t.ZDisplay(root.right)
}

// 中序遍历非递归,左 - 根 - 右
func (t *Tree) NoZDisplay(root *Node) {
	if root == nil {
		return
	}
	// 借助栈结构,先进后出
	curr := root
	stack := list.New()
	for curr != nil || stack.Len() != 0 {
		if curr != nil {
			// 所有的左子树放入栈中
			stack.PushBack(curr)
			curr = curr.left
		} else {
			tmp := stack.Back()
			stack.Remove(tmp)
			if tmp.Value != nil {
				fmt.Println(tmp.Value.(*Node).data)
				curr = tmp.Value.(*Node).right // 让当前出栈的节点的右子树进栈
			}
		}
	}
}

// 后序遍历
func (t *Tree) HDisplay(root *Node) {
	if root == nil {
		return
	}
	t.HDisplay(root.left)
	t.HDisplay(root.right)
	fmt.Println(root.data)
}

// 后序遍历非递归
// 后续遍历解决的问题
// 当给定一个节点时,输出该节点的所有祖先
// 输出根结点到叶子节点的所有路径
// 求每条路径上的节点值之和
func (t *Tree) NoHDisplay(root *Node) {
	if root == nil {
		return
	}
	var pre *Node = nil
	stack := list.New()
	for root != nil || stack.Len() != 0 {
		// 将左右左子树存放到栈中
		for root != nil {
			stack.PushBack(root)
			root = root.left
		}
		// 取出节点
		tmp := stack.Back()
		root = tmp.Value.(*Node)
		stack.Remove(tmp)
		// 当前节点如果右节点为空,或者等于上次访问的节点,输出该节点,比把已经输出的节点打上标记
		if root.right == nil || root.right == pre {
			fmt.Println(root.data)
			pre = root
			root = nil // 右子树访问了,重新下一轮的从栈那元素
		} else {
			// 如果不能输出,重新入栈,再对当前节点的右子数重复入栈过程
			stack.PushBack(root)
			root = root.right
		}
	}
}

// 按层遍历
func (t *Tree) CDisplay(root *Node) {
	if root == nil {
		return
	}
	queue := list.New()
	queue.PushBack(root)
	for queue.Len() != 0 {
		tmp := queue.Front()
		queue.Remove(tmp)
		cur := tmp.Value.(*Node)
		fmt.Println(cur.data)
		if cur.left != nil {
			queue.PushBack(cur.left)
		}
		if cur.right != nil {
			queue.PushBack(cur.right)
		}
	}

}

func main() {
	t := &Tree{
		root: nil,
	}

	number := []int{1, 4, 3, 2}
	// 创建一棵树
	for _, val := range number {
		t.root = t.createTree(t.root, val)
	}
	//
	// IntMap := make(map[int]int, 0)
	// for i := 0; i < 20; i++ {
	// 	num := rand.Int() % 10
	// 	if _, ok := IntMap[num]; ok {
	// 		continue
	// 	}
	// 	t.root = t.createTree(t.root, num)
	// 	IntMap[num] = num
	// }

	t.QDisplay(t.root)
	fmt.Println("-----------")
	t.NoQDisplay(t.root)

	// t.ZDisplay(t.root)
	// fmt.Println("-----------")
	// t.NoZDisplay(t.root)
	//
	// t.HDisplay(t.root)
	// fmt.Println("-----------")
	// t.NoHDisplay(t.root)
	//
	// t.CDisplay(t.root)
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Steps-of-time

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值