数据结构:二叉树

二叉树的特点

  1. 二叉树中每个节点最多有两棵子树,称为左子树、右子树;
  2. 左子树和右子树是有顺序的,有左右之分,次序不能随意颠倒;
  3. 即使某个节点只有一个子树,也要区分左右子树。

即:最多两棵树,还要分左右。

  1. 完全二叉树:只有底层没满,且按顺序排列在左边的二叉树。
  2. 满二叉树:所有节点都满了的二叉树
  3. 二叉搜索树:节点分大小,左边>中间>右边。
  4. 平衡二叉树:左右子树的高度差最大为1。
  5. 平衡二叉搜索树:集合二叉搜索树和平衡二叉树两者特点的树,比如AVL树。

二叉树的存储

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

树的遍历

前序遍历

前序遍历-递归

func preOrder(t *TreeNode) {
	if t == nil {
		return
	}
	fmt.Println(t.Val)
	preOrder(t.Left)
	preOrder(t.Right)
}

前序遍历-非递归

中序遍历

中序遍历-递归

func inOrder(t *TreeNode) {
	if t == nil {
		return
	}
	inOrder(t.Left)
	fmt.Println(t.Val)
	inOrder(t.Right)
}

中序遍历-非递归

// 使用栈来记录树上的节点,栈顶的节点即是当前访问的节点

后序遍历

后序遍历-递归

func postOrder(t *TreeNode) {
	if t == nil {
		return
	}
	postOrder(t.Left)
	postOrder(t.Right)
	fmt.Println(t.Val)
}

后序遍历-非递归

DFS和BFS搜索

广度优先搜索(Breath First Search,BFS,又称层序遍历。一般采用队列进行遍历辅助。)

func bfs(p *TreeNode) []int {
	res := make([]int, 0)
	if p == nil {
		return res
	}

// BFS需要使用一个 **队列** 协助,此处用slice模拟队列
	queue := []*TreeNode{p}
	for len(queue) > 0 {    //每一轮是不同层
		length := len(queue)
		for length > 0 {    // 同层遍历
			length--
			if queue[0].Left != nil {
				queue = append(queue, queue[0].Left)
			}
			if queue[0].Right != nil {
				queue = append(queue, queue[0].Right)
			}
			res = append(res, queue[0].Val)
			queue = queue[1:]
		}
	}

	return res
}

深度优先搜索(Depth First Search,DFS。一般采用栈进行遍历辅助,可用递归来实现栈。)

func DFS(root *TreeNode) []int {
    if root == nil {
        return
    }

    var res []int
    res = append(res, root.Val)

    DFS(root.Left)
    DFS(root.Right)

    return res
}

计算二叉树的节点个数

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func countNodes(root *TreeNode) int {
    if root == nil {
        return 0
    }

    return countNodes(root.Left) + countNodes(root.Right) + 1
}

计算二叉树的深度

func maxDepth(root *TreeNode) int {
    if root == nil {
        return 0
    }

    return 1 + max(maxDepth(root.Left), maxDepth(root.Right))
}

func max(x,y int) int {
    if x > y {
        return x
    }
    
    return y
}

平衡二叉树

判断一棵二叉树是否是平衡二叉树

func isBalanced(root *TreeNode) bool {
	if root == nil {
		return true
	}
	leftHeight := height(root.Left)
	rightHeight := height(root.Right)
	if leftHeight-rightHeight < -1 || leftHeight-rightHeight > 1 {
		return false
	}

	return isBalanced(root.Left) && isBalanced(root.Right)
}

func height(node *TreeNode) int {
	if node == nil {
		return 0
	}

	return 1 + max(height(node.Left), height(node.Right))
}

func max(a, b int) int {
	if a > b {
		return a
	}

	return b
}

合并两个二叉树

func mergeTrees(root1 *TreeNode, root2 *TreeNode) *TreeNode {
	if root1 == nil && root2 == nil {
		return nil
	} else if root1 == nil {
		return root2
	} else if root2 == nil {
		return root1
	} else {
		root1.Val += root2.Val
		root1.Left = mergeTrees(root1.Left, root2.Left)
		root1.Right = mergeTrees(root1.Right, root2.Right)
		return root1
	}
}

反转二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func invertTree(root *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }

    left := invertTree(root.Left)
    right := invertTree(root.Right)

    root.Left = right
    root.Right = left
    
    return root
}

判断两棵二叉树是否相同

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSameTree(p *TreeNode, q *TreeNode) bool {
    if (p == nil) && (q == nil) {
        return true
    }

    if (p == nil) || (q == nil) {
        return false
    }

    if p.Val != q.Val {
        return false
    }

    return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)    
}

打印二叉树的所有路径

输入:root = [1,2,3,null,5]
输出:["1->2->5","1->3"]

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
var paths []string

func binaryTreePaths(root *TreeNode) []string {
    paths = []string{}
    constructPaths(root, "")
    return paths
}

func constructPaths(root *TreeNode, path string) {
    if root != nil {
        pathSB := path
        pathSB += strconv.Itoa(root.Val)
        if root.Left == nil && root.Right == nil {
            paths = append(paths, pathSB)
        } else {
            pathSB += "->"
            constructPaths(root.Left, pathSB)
            constructPaths(root.Right, pathSB)
        }
    }
}

计算二叉树的最小深度

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func minDepth(root *TreeNode) int {
    if root == nil {
		return 0
	}

	if root.Left == nil {
		return minDepth(root.Right) + 1
	}

	if root.Right == nil {
		return minDepth(root.Left) + 1
	}

	return min(minDepth(root.Left), minDepth(root.Right)) + 1  
}

func min(a, b int) int {
    if a < b {
        return a
    }

    return b
}

二叉树的最近公共祖先

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil {
        return nil
    }

    if root.Val == p.Val || root.Val == q.Val {
        return root
    }

    left := lowestCommonAncestor(root.Left, p, q)
    right := lowestCommonAncestor(root.Right, p, q)
    if left != nil && right != nil {
        return root
    }

    if left == nil {
        return right
    }
    
    return left
}

判断是否是轴对称的对称二叉树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSymmetric(root *TreeNode) bool {
    if root == nil {
        return true
    }

    return compare(root.Left, root.Right)
}

func compare(node1 *TreeNode, node2 *TreeNode) bool {
    if node1 == nil && node2 == nil {
        return true
    }

    if node1 == nil || node2 == nil {
        return false
    }

    if node1.Val != node2.Val {
        return false
    }


    return compare(node1.Left, node2.Right) && compare(node1.Right, node2.Left)
}

二分搜索树(BST,Binary Search Tree)

  1. 二分搜索树也是一种二叉树,但二分搜索树种每个节点的值都要大于其左子树所有节点的值,小于其右子树所有节点的值;
  2. 每一棵子树也是二分搜索树。

验证是否是二叉搜索树

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool {
    if root == nil{
        return true
    }
    var stack []*TreeNode
    cur := root
    var prev *TreeNode
    
    for len(stack)>0 || cur!=nil{
        if cur!=nil{
            stack = append(stack,cur)
            cur = cur.Left
        }else{
            cur = stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            if prev!=nil &&prev.Val >= cur.Val{
                return false
            }
            
            prev = cur
            cur = cur.Right
        }
    }
    
    return true
}

平衡二叉树(AVL树、红黑树)

线段树

Trie树(又称字典树或前缀树)