Skip to content

Commit

Permalink
feat(go/tree): support array binary tree (#655)
Browse files Browse the repository at this point in the history
  • Loading branch information
Reanon authored Jul 26, 2023
1 parent 027bdd6 commit 575bcf5
Show file tree
Hide file tree
Showing 15 changed files with 223 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func preOrderI(root *TreeNode, res *[]*TreeNode) {
if root == nil {
return
}
if int(root.Val) == 7 {
if (root.Val).(int) == 7 {
// 记录解
*res = append(*res, root)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func preOrderII(root *TreeNode, res *[][]*TreeNode, path *[]*TreeNode) {
}
// 尝试
*path = append(*path, root)
if int(root.Val) == 7 {
if root.Val.(int) == 7 {
// 记录解
*res = append(*res, *path)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func preOrderIII(root *TreeNode, res *[][]*TreeNode, path *[]*TreeNode) {
}
// 尝试
*path = append(*path, root)
if int(root.Val) == 7 {
if root.Val.(int) == 7 {
// 记录解
*res = append(*res, *path)
*path = (*path)[:len(*path)-1]
Expand Down
8 changes: 4 additions & 4 deletions codes/go/chapter_backtracking/preorder_traversal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

func TestPreorderTraversalICompact(t *testing.T) {
/* 初始化二叉树 */
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 7, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树")
PrintTree(root)

Expand All @@ -30,7 +30,7 @@ func TestPreorderTraversalICompact(t *testing.T) {

func TestPreorderTraversalIICompact(t *testing.T) {
/* 初始化二叉树 */
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 7, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树")
PrintTree(root)

Expand All @@ -50,7 +50,7 @@ func TestPreorderTraversalIICompact(t *testing.T) {

func TestPreorderTraversalIIICompact(t *testing.T) {
/* 初始化二叉树 */
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 7, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树")
PrintTree(root)

Expand All @@ -70,7 +70,7 @@ func TestPreorderTraversalIIICompact(t *testing.T) {

func TestPreorderTraversalIIITemplate(t *testing.T) {
/* 初始化二叉树 */
root := ArrToTree([]any{1, 7, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 7, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树")
PrintTree(root)

Expand Down
101 changes: 101 additions & 0 deletions codes/go/chapter_tree/array_binary_tree.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// File: array_binary_tree.go
// Created Time: 2023-07-24
// Author: Reanon ([email protected])

package chapter_tree

/* 数组表示下的二叉树类 */
type arrayBinaryTree struct {
tree []any
}

/* 构造方法 */
func newArrayBinaryTree(arr []any) *arrayBinaryTree {
return &arrayBinaryTree{
tree: arr,
}
}

/* 节点数量 */
func (abt *arrayBinaryTree) size() int {
return len(abt.tree)
}

/* 获取索引为 i 节点的值 */
func (abt *arrayBinaryTree) val(i int) any {
// 若索引越界,则返回 null ,代表空位
if i < 0 || i >= abt.size() {
return nil
}
return abt.tree[i]
}

/* 获取索引为 i 节点的左子节点的索引 */
func (abt *arrayBinaryTree) left(i int) int {
return 2*i + 1
}

/* 获取索引为 i 节点的右子节点的索引 */
func (abt *arrayBinaryTree) right(i int) int {
return 2*i + 2
}

/* 获取索引为 i 节点的父节点的索引 */
func (abt *arrayBinaryTree) parent(i int) int {
return (i - 1) / 2
}

/* 层序遍历 */
func (abt *arrayBinaryTree) levelOrder() []any {
var res []any
// 直接遍历数组
for i := 0; i < abt.size(); i++ {
if abt.val(i) != nil {
res = append(res, abt.val(i))
}
}
return res
}

/* 深度优先遍历 */
func (abt *arrayBinaryTree) dfs(i int, order string, res *[]any) {
// 若为空位,则返回
if abt.val(i) == nil {
return
}
// 前序遍历
if order == "pre" {
*res = append(*res, abt.val(i))
}
abt.dfs(abt.left(i), order, res)
// 中序遍历
if order == "in" {
*res = append(*res, abt.val(i))
}
abt.dfs(abt.right(i), order, res)
// 后序遍历
if order == "post" {
*res = append(*res, abt.val(i))
}
}

/* 前序遍历 */
func (abt *arrayBinaryTree) preOrder() []any {
var res []any
abt.dfs(0, "pre", &res)
return res
}

/* 中序遍历 */
func (abt *arrayBinaryTree) inOrder() []any {
var res []any
abt.dfs(0, "in", &res)
return res
}

/* 后序遍历 */
func (abt *arrayBinaryTree) postOrder() []any {
var res []any
abt.dfs(0, "post", &res)
return res
}
47 changes: 47 additions & 0 deletions codes/go/chapter_tree/array_binary_tree_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// File: array_binary_tree_test.go
// Created Time: 2023-07-24
// Author: Reanon ([email protected])

package chapter_tree

import (
"fmt"
"testing"

. "github.com/krahets/hello-algo/pkg"
)

func TestArrayBinaryTree(t *testing.T) {
// 初始化二叉树
// 这里借助了一个从数组直接生成二叉树的函数
arr := []any{1, 2, 3, 4, nil, 6, 7, 8, 9, nil, nil, 12, nil, nil, 15}
root := SliceToTree(arr)
fmt.Println("\n初始化二叉树")
fmt.Println("二叉树的数组表示:")
fmt.Println(arr)
fmt.Println("二叉树的链表表示:")
PrintTree(root)

// 数组表示下的二叉树类
abt := newArrayBinaryTree(arr)

// 访问节点
i := 1
l := abt.left(i)
r := abt.right(i)
p := abt.parent(i)
fmt.Println("\n当前节点的索引为", i, ",值为", abt.val(i))
fmt.Println("其左子节点的索引为", l, ",值为", abt.val(l))
fmt.Println("其右子节点的索引为", r, ",值为", abt.val(r))
fmt.Println("其父节点的索引为", p, ",值为", abt.val(p))

// 遍历树
res := abt.levelOrder()
fmt.Println("\n层序遍历为:", res)
res = abt.preOrder()
fmt.Println("前序遍历为:", res)
res = abt.inOrder()
fmt.Println("中序遍历为:", res)
res = abt.postOrder()
fmt.Println("后序遍历为:", res)
}
14 changes: 7 additions & 7 deletions codes/go/chapter_tree/avl_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ func (t *aVLTree) insertHelper(node *TreeNode, val int) *TreeNode {
return NewTreeNode(val)
}
/* 1. 查找插入位置,并插入节点 */
if val < node.Val {
if val < node.Val.(int) {
node.Left = t.insertHelper(node.Left, val)
} else if val > node.Val {
} else if val > node.Val.(int) {
node.Right = t.insertHelper(node.Right, val)
} else {
// 重复节点不插入,直接返回
Expand All @@ -144,9 +144,9 @@ func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode {
return nil
}
/* 1. 查找节点,并删除之 */
if val < node.Val {
if val < node.Val.(int) {
node.Left = t.removeHelper(node.Left, val)
} else if val > node.Val {
} else if val > node.Val.(int) {
node.Right = t.removeHelper(node.Right, val)
} else {
if node.Left == nil || node.Right == nil {
Expand All @@ -167,7 +167,7 @@ func (t *aVLTree) removeHelper(node *TreeNode, val int) *TreeNode {
for temp.Left != nil {
temp = temp.Left
}
node.Right = t.removeHelper(node.Right, temp.Val)
node.Right = t.removeHelper(node.Right, temp.Val.(int))
node.Val = temp.Val
}
}
Expand All @@ -184,10 +184,10 @@ func (t *aVLTree) search(val int) *TreeNode {
cur := t.root
// 循环查找,越过叶节点后跳出
for cur != nil {
if cur.Val < val {
if cur.Val.(int) < val {
// 目标节点在 cur 的右子树中
cur = cur.Right
} else if cur.Val > val {
} else if cur.Val.(int) > val {
// 目标节点在 cur 的左子树中
cur = cur.Left
} else {
Expand Down
12 changes: 6 additions & 6 deletions codes/go/chapter_tree/binary_search_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ func (bst *binarySearchTree) search(num int) *TreeNode {
node := bst.root
// 循环查找,越过叶节点后跳出
for node != nil {
if node.Val < num {
if node.Val.(int) < num {
// 目标节点在 cur 的右子树中
node = node.Right
} else if node.Val > num {
} else if node.Val.(int) > num {
// 目标节点在 cur 的左子树中
node = node.Left
} else {
Expand All @@ -77,15 +77,15 @@ func (bst *binarySearchTree) insert(num int) {
return
}
pre = cur
if cur.Val < num {
if cur.Val.(int) < num {
cur = cur.Right
} else {
cur = cur.Left
}
}
// 插入节点
node := NewTreeNode(num)
if pre.Val < num {
if pre.Val.(int) < num {
pre.Right = node
} else {
pre.Left = node
Expand All @@ -107,7 +107,7 @@ func (bst *binarySearchTree) remove(num int) {
break
}
pre = cur
if cur.Val < num {
if cur.Val.(int) < num {
// 待删除节点在右子树中
cur = cur.Right
} else {
Expand Down Expand Up @@ -147,7 +147,7 @@ func (bst *binarySearchTree) remove(num int) {
tmp = tmp.Left
}
// 递归删除节点 tmp
bst.remove(tmp.Val)
bst.remove(tmp.Val.(int))
// 用 tmp 覆盖 cur
cur.Val = tmp.Val
}
Expand Down
4 changes: 2 additions & 2 deletions codes/go/chapter_tree/binary_tree_bfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
)

/* 层序遍历 */
func levelOrder(root *TreeNode) []int {
func levelOrder(root *TreeNode) []any {
// 初始化队列,加入根节点
queue := list.New()
queue.PushBack(root)
// 初始化一个切片,用于保存遍历序列
nums := make([]int, 0)
nums := make([]any, 0)
for queue.Len() > 0 {
// 队列出队
node := queue.Remove(queue.Front()).(*TreeNode)
Expand Down
2 changes: 1 addition & 1 deletion codes/go/chapter_tree/binary_tree_bfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func TestLevelOrder(t *testing.T) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
root := ArrToTree([]any{1, 2, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 2, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树: ")
PrintTree(root)

Expand Down
2 changes: 1 addition & 1 deletion codes/go/chapter_tree/binary_tree_dfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
. "github.com/krahets/hello-algo/pkg"
)

var nums []int
var nums []any

/* 前序遍历 */
func preOrder(node *TreeNode) {
Expand Down
2 changes: 1 addition & 1 deletion codes/go/chapter_tree/binary_tree_dfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
func TestPreInPostOrderTraversal(t *testing.T) {
/* 初始化二叉树 */
// 这里借助了一个从数组直接生成二叉树的函数
root := ArrToTree([]any{1, 2, 3, 4, 5, 6, 7})
root := SliceToTree([]any{1, 2, 3, 4, 5, 6, 7})
fmt.Println("\n初始化二叉树: ")
PrintTree(root)

Expand Down
2 changes: 1 addition & 1 deletion codes/go/pkg/print_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func PrintHeap(h []any) {
fmt.Printf("堆的数组表示:")
fmt.Printf("%v", h)
fmt.Printf("\n堆的树状表示:\n")
root := ArrToTree(h)
root := SliceToTree(h)
PrintTree(root)
}

Expand Down
Loading

0 comments on commit 575bcf5

Please sign in to comment.