diff --git a/data_structure/binarytree.go b/data_structure/binarytree.go new file mode 100644 index 00000000..d361fe6c --- /dev/null +++ b/data_structure/binarytree.go @@ -0,0 +1,264 @@ +package data_structure + +import "fmt" + +type TreeNode struct { + Val int + Left *TreeNode + Right *TreeNode +} + +// 前序递归遍历 +func preorderTraversalRecursion(root *TreeNode) { + if root == nil { + return + } + // 先访问根再访问左右 + fmt.Printf("%v ", root.Val) + preorderTraversalRecursion(root.Left) + preorderTraversalRecursion(root.Right) +} + +// 前序非递归遍历 +func preorderTraversalNotRecursion(root *TreeNode) []int { + // 非递归 + if root == nil { + return nil + } + result := make([]int, 0) + stack := make([]*TreeNode, 0) + + for root != nil || len(stack) != 0 { + for root != nil { + // 前序遍历,所以先保存结果 + result = append(result, root.Val) + stack = append(stack, root) + root = root.Left + } + // pop + node := stack[len(stack)-1] + stack = stack[:len(stack)-1] + root = node.Right + } + + return result +} + +// 中序非递归遍历 +func inorderTraversalNotRecursion(root *TreeNode) []int { + result := make([]int, 0) + if root == nil { + return result + } + stack := make([]*TreeNode, 0) + for len(stack)> 0 || root != nil { + for root != nil { + stack = append(stack, root) + root = root.Left // 一直向左 + } + // 弹出 + val := stack[len(stack)-1] + stack = stack[:len(stack)-1] + result = append(result, val.Val) + root = val.Right + } + + return result +} + +// 后序非递归遍历 +func postorderTraversalNotRecursion(root *TreeNode) []int { + // 通过lastVisit标识右子节点是否已经弹出 + if root == nil { + return nil + } + result := make([]int, 0) + stack := make([]*TreeNode, 0) + var lastVisit *TreeNode + for root != nil || len(stack) != 0 { + for root != nil { + stack = append(stack, root) + root = root.Left + } + // 这里先看看,先不弹出 + node := stack[len(stack)-1] + // 根节点必须在右节点弹出之后,再弹出 + if node.Right == nil || node.Right == lastVisit { + stack = stack[:len(stack)-1] // pop + result = append(result, node.Val) + // 标记当前这个节点已经弹出过 + lastVisit = node + } else { + root = node.Right + } + } + + return result +} + +// DFS 深度搜索-从上到下 +func preorderTraversalDFS(root *TreeNode) []int { + result := make([]int, 0) + dfs(root, &result) + + return result +} + +// V1:深度遍历,结果指针作为参数传入到函数内部 +func dfs(root *TreeNode, result *[]int) { + if root == nil { + return + } + *result = append(*result, root.Val) + dfs(root.Left, result) + dfs(root.Right, result) +} + +// DFS 深度搜索-从下向上(分治法) +func preorderTraversalDFSDivide(root *TreeNode) []int { + result := divideAndConquer(root) + + return result +} +func divideAndConquer(root *TreeNode) []int { + result := make([]int, 0) + // 返回条件(null & leaf) + if root == nil { + return result + } + // 分治(Divide) + left := divideAndConquer(root.Left) + right := divideAndConquer(root.Right) + // 合并结果(Conquer) + result = append(result, root.Val) + result = append(result, left...) + result = append(result, right...) + + return result +} + +// BFS 层次遍历 +func levelOrderBFS(root *TreeNode) [][]int { + // 通过上一层的长度确定下一层的元素 + result := make([][]int, 0) + if root == nil { + return result + } + queue := make([]*TreeNode, 0) + queue = append(queue, root) + for len(queue)> 0 { + list := make([]int, 0) + // 为什么要取length? + // 记录当前层有多少元素(遍历当前层,再添加下一层) + l := len(queue) + for i := 0; i < l; i++ { + // 出队列 + level := queue[0] + queue = queue[1:] + list = append(list, level.Val) + if level.Left != nil { + queue = append(queue, level.Left) + } + if level.Right != nil { + queue = append(queue, level.Right) + } + } + result = append(result, list) + } + + return result +} + +// 归并排序 +func MergeSort(nums []int) []int { + return mergeSort(nums) +} +func mergeSort(nums []int) []int { + if len(nums) <= 1 { + return nums + } + // 分治法:divide 分为两段 + mid := len(nums) / 2 + left := mergeSort(nums[:mid]) + right := mergeSort(nums[mid:]) + // 合并两段数据 + result := merge(left, right) + return result +} +func merge(left, right []int) (result []int) { + // 两边数组合并游标 + l := 0 + r := 0 + // 注意不能越界 + for l < len(left) && r < len(right) { + // 谁小合并谁 + if left[l]> right[r] { + result = append(result, right[r]) + r++ + } else { + result = append(result, left[l]) + l++ + } + } + // 剩余部分合并 + result = append(result, left[l:]...) + result = append(result, right[r:]...) + return +} + +// 快速排序 +func QuickSort(nums []int) []int { + // 思路:把一个数组分为左右两段,左段小于右段,类似分治法没有合并过程 + quickSort(nums, 0, len(nums)-1) + return nums + +} +func quickSort(nums []int, start, end int) { + // 原地交换,所以传入交换索引 + if start < end { + // 分治法:divide + pivot := partition(nums, start, end) + quickSort(nums, 0, pivot-1) + quickSort(nums, pivot+1, end) + } +} +func partition(nums []int, start, end int) int { + // 分区 + p := nums[end] + i := start + for j := start; j < end; j++ { + if nums[j] < p { + swap(nums, i, j) + i++ + } + } + // 把中间的值换为用于比较的基准值 + swap(nums, i, end) + return i +} +func swap(nums []int, i, j int) { + t := nums[i] + nums[i] = nums[j] + nums[j] = t +} + +/* +常见题目示例 +*/ + +// 给定一个二叉树,找出去最大深度 +func maxDepth(root *TreeNode) int { + // 返回条件处理 + if root == nil { + return 0 + } + // divide:分左右子树分别计算 + left := maxDepth(root.Left) + right := maxDepth(root.Right) + + // conquer:合并左右子树结果 + if left> right { + return left + 1 + } + return right + 1 +} diff --git a/data_structure/binarytree_test.go b/data_structure/binarytree_test.go new file mode 100644 index 00000000..addaac4c --- /dev/null +++ b/data_structure/binarytree_test.go @@ -0,0 +1,76 @@ +package data_structure + +import ( + "fmt" + "testing" +) + +var treeNode *TreeNode = &TreeNode{ + Val: 1, + Left: &TreeNode{ + Val: 2, + Left: &TreeNode{ + Val: 4, + Right: &TreeNode{ + Val: 6, + Left: &TreeNode{Val: 7}, + Right: &TreeNode{Val: 8}, + }, + }, + }, + Right: &TreeNode{ + Val: 3, + Right: &TreeNode{Val: 5}, + }, +} + +func TestPreorderTraversalRecursion(t *testing.T) { + preorderTraversalRecursion(treeNode) +} + +func TestPreorderTraversalNotRecursion(t *testing.T) { + result := preorderTraversalNotRecursion(treeNode) + fmt.Println(result) +} + +func TestInorderTraversalNotRecursion(t *testing.T) { + result := inorderTraversalNotRecursion(treeNode) + fmt.Println(result) +} + +func TestPostorderTraversalNotRecursion(t *testing.T) { + result := postorderTraversalNotRecursion(treeNode) + fmt.Println(result) +} + +func TestPreorderTraversalDFS(t *testing.T) { + result := preorderTraversalDFS(treeNode) + fmt.Println(result) +} + +func TestPreorderTraversalDFSDivide(t *testing.T) { + result := preorderTraversalDFSDivide(treeNode) + fmt.Println(result) +} + +func TestLevelOrderBFS(t *testing.T) { + result := levelOrderBFS(treeNode) + fmt.Println(result) +} + +func TestMergeSort(t *testing.T) { + nums := []int{3, 2, 9, 4, 6, 8, 1, 5} + result := MergeSort(nums) + fmt.Println(result) +} + +func TestQuickSort(t *testing.T) { + nums := []int{3, 2, 9, 4, 6, 8, 1, 5} + result := QuickSort(nums) + fmt.Println(result) +} + +func TestMaxDepth(t *testing.T) { + result := maxDepth(treeNode) + fmt.Println(result) +} diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..ab64e2c0 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module algorithm-pattern + +go 1.22.8