跳至主要內容

树(Tree)

Steven大约 2 分钟datastructure

遍历

测试用例
package org.example.test1;

import org.example.datastructure.BinaryTreeNode;
import org.example.util.BinaryTreeTraversalUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class BinaryTreeTraversalTest {
    @Test
    void test() {
        /*
          3
         2  5
        1  4  7
             6
         */
        BinaryTreeNode root = new BinaryTreeNode(3);
        {
            BinaryTreeNode l = new BinaryTreeNode(2);
            BinaryTreeNode r = new BinaryTreeNode(5);
            BinaryTreeNode ll = new BinaryTreeNode(1);
            BinaryTreeNode rl = new BinaryTreeNode(4);
            BinaryTreeNode rr = new BinaryTreeNode(7);
            BinaryTreeNode rrl = new BinaryTreeNode(6);
            root.setLeft(l);
            root.setRight(r);
            l.setLeft(ll);
            r.setLeft(rl);
            r.setRight(rr);
            rr.setLeft(rrl);
        }
        // 前序
        {
            List<Integer> v1 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsBAC(root, (value) -> {
                v1.add(value);
            });
            log.info("前序: {}", v1);
            // 非递归
            List<Integer> v2 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsBAC2(root, (value) -> {
                v2.add(value);
            });
            Assertions.assertArrayEquals(v1.toArray(), v2.toArray());
        }
        // 中序
        {
            List<Integer> v1 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsABC(root, (value) -> {
                v1.add(value);
            });
            log.info("中序: {}", v1);
            // 非递归
            ArrayList<Integer> v2 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsABC2(root, (value) -> {
                v2.add(value);
            });
            Assertions.assertArrayEquals(v1.toArray(), v2.toArray());
        }
        // 后序
        {
            List<Integer> v1 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsACB(root, (value) -> {
                v1.add(value);
            });
            log.info("后序: {}", v1);
            // 非递归
            ArrayList<Integer> v2 = new ArrayList<>();
            BinaryTreeTraversalUtil.dfsACB2(root, (value) -> {
                v2.add(value);
            });
            Assertions.assertArrayEquals(v1.toArray(), v2.toArray());
        }
        // 层序遍历
        {
            List<List<Integer>> tree = new ArrayList<>();
            BinaryTreeTraversalUtil.bfs(root, (level, val) -> {
                if (tree.size() > level-1) {
                    tree.get(level-1).add(val);
                } else {
                    List<Integer> flow = new ArrayList<>();
                    flow.add(val);
                    tree.add(flow);
                }
            });
            // show
            for (int i = 0; i < tree.size(); i++) {
                List<String> flow = tree.get(i).stream()
                        .map(v -> v==null ? "#" : String.valueOf(v))
                        .collect(Collectors.toList());
                log.info("{}: {}", i, flow);
            }
        }
    }
}

相关例题:DFS

相关例题:BFS

提示

在完全遍历的情况下,解题方式中,DFS 效率优于 BFS (猜测:不用创建内存的缘故把)

深度优先遍历(DFS)

概要

  • 前序:中左右
  • 中序:左中右
  • 后序:左右中

递归法

/**
 * 前序:中左右
 */
void traversal(cur, vec) {
  if (cur == null) {
    return;
  }
  vec.push(cur->val); // 中
  traversal(cur->left, vec); // 左
  traversal(cur->right, vec); // 右
}

非递归法

todo pseudo code

// 前序:中左右
BinaryTreeNode cur = root;
Stack<BinaryTreeNode> stack = new Stack<>();
while(cur!=null || !stack.isEmpty()) {
    if (cur != null) {
        func.accept(cur.getVal());
        stack.push(cur.getRight());
        stack.push(cur.getLeft());
    }
    cur = stack.pop();
}

层序遍历(广度优先,BFS)【重要】

public static void bfs(BinaryTreeNode root, BiConsumer<Integer, Integer> func) {
    Queue<BinaryTreeNode> queue = new LinkedList<>();
    int size = 1; // ❗记录当前层数量
    int level = 1;
    queue.add(root);
    while (!queue.isEmpty()) {
        while(size > 0) {
            size--;
            BinaryTreeNode cur = queue.poll();
            func.accept(level, cur == null ? null : cur.getVal());
            if (cur == null) {
                continue;
            }
            queue.add(cur.getLeft());
            queue.add(cur.getRight());
        }
        size = queue.size();
        level++;
    }
}

问题:深度

相关例题:

easy

问题:反转

相关例题:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        TreeNode l = invertTree(root.left);
        TreeNode r = invertTree(root.right);
        root.left = r;
        root.right = l;
        return root;
    }
}

问题:判断是否对称

相关问题:

双指针

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true;
        }
        return xx(root.left, root.right);
    }
    boolean xx(TreeNode left, TreeNode right) {
        if (left == null && right == null) return true;
        if (left == null || right == null) return false;
        if (left.val != right.val) return false;
        return xx(left.left, right.right) && xx(left.right, right.left);
    }
}