【数据结构与算法(Java)】二叉树的前序、中序、后序的遍历与查找

1. 思路

1.1 遍历思路

(1)前序

  1. 打印当前节点数值
  2. 若左树非空,递归左树
  3. 若右树非空,递归右树

(2)中序

  1. 若左树非空,递归左树
  2. 打印当前节点数值
  3. 若右树非空,递归右树

(3)后序

  1. 若左树非空,递归左树
  2. 若右树非空,递归右树
  3. 打印当前节点数值

1.2 查找思路

(1)前序

  1. 检查当前节点值,若与输入值相等,则返回当前节点
  2. 设置临时节点变量node,用于储存找到的节点(初始化为null)
  3. 查询左树
    • 若左树非空,递归左树,并将返回结果赋值给临时变量node
    • 递归完成,若node非null,说明找到,返回node
  4. 查询右树
    • 若右树非空,递归右树,并将返回结果赋值给临时变量node
    • 返回node(若node非空,则找到;否则未找到,返回null)

(2)中序

  1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
  2. 查询左树
    • 若左树非空,递归左树,并将返回结果赋值给临时变量node
    • 递归完成,若node非null,说明找到,返回node
  3. 检查当前节点值,若与输入值相等,则返回当前节点
  4. 查询右树
    • 若右树非空,递归右树,并将返回结果赋值给临时变量node
    • 返回node(若node非空,则找到;否则未找到,返回null)

(3)后序

  1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
  2. 查询左树:
    • 若左树非空,递归左树,并将返回结果赋值给临时变量node
    • 递归完成,若node非null,说明找到,返回node
  3. 查询右树
    • 若右树非空,递归右树,并将返回结果赋值给临时变量node
    • 返回node(若node非空,则找到;否则未找到,返回null)
  4. 检查当前节点
    • 检查当前节点值,若与输入值相等,则返回当前节点
    • 否则,返回null

2. 基本结构

2.1 TreeNode (二叉树节点)

  • int index;

  • TreeNode leftNode;

  • TreeNode rightNode;

  • preOrderTraversal()

  • infixOrderTraversal()

  • postOrderTraversal()

  • preOrderSearch()

  • infixOrderSearch()

  • postOrderSearch()

2.2 BinaryTree(二叉树)

  • TreeNode rootNode;
    // 一下方法调用TreeNode内的相应方法实现查找或遍历
  • preOrderTraversal()
  • infixOrderTraversal()
  • postOrderTraversal()
  • preOrderSearch()
  • infixOrderSearch()
  • postOrderSearch()

3. 代码实现

public class BinaryTree {
    private TreeNode rootNode;
    // for test
    public static ArrayList<Integer> orderList = new ArrayList<>();

    // getter and setter
    public TreeNode getRootNode() {
        return rootNode;
    }
    public void setRootNode(TreeNode rootNode) {
        this.rootNode = rootNode;
    }

    /**
     * 前序遍历
     */
    public void preOrderTraversal() {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        } else {
            this.rootNode.preOrderTraversal();
        }
    }
    /**
     * 中序遍历
     */
    public void infixOrderTraversal() {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        } else {
            this.rootNode.infixOrderTraversal();
        }
    }
    /**
     * 后序遍历
     */
    public void postOrderTraversal() {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        } else {
            this.rootNode.postOrderTraversal();
        }
    }

    /**
     * 前序查找
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode preOrderSearch(int searchIndex) {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        }
        return this.rootNode.preOrderSearch(searchIndex);
    }
    /**
     * 中序查找
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode infixOrderSearch(int searchIndex) {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        }
        return this.rootNode.infixOrderSearch(searchIndex);
    }
    /**
     * 后序查找
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode postOrderSearch(int searchIndex) {
        if (this.rootNode == null) {
            throw new RuntimeException("empty");
        }
        return this.rootNode.postOrderSearch(searchIndex);
    }

    /**
     * 牛客网算法题:按照层次打印这棵二叉树。
     *
     * 给定二叉树的根结点root,请返回打印结果,结果按照每一层一个数组进行储存,
     * 所有数组的顺序按照层数从上往下,且每一层的数组内元素按照从左往右排列。保证结点数小于等于500。
     * @param root - 根节点
     * @return - 二维数组,每个数组储存的是每层数据的数组
     */
    public int[][] printTree(TreeNode root) {
        // 0. check root
        if (root == null) {
            return null;
        }

        ArrayList<ArrayList<TreeNode>> arrayList = new ArrayList<>();

        boolean hasNextLevel = true;
        TreeNode currentNode = root;
        while (hasNextLevel) {
            ArrayList<TreeNode> currentLevelNodeList = new ArrayList<>();
            // if it's the first level
            if (arrayList.isEmpty()) {
                currentLevelNodeList.add(root);
                if (root.getLeftNode() == null && root.getRightNode() == null) {
                    hasNextLevel = false;
                }
            }
            // not the first level
            else {
                // add current level node list into the arrayList and check next level
                hasNextLevel = false;
                for (TreeNode node : arrayList.get(arrayList.size() - 1)) {
                    if (node.getLeftNode() != null) {
                        currentLevelNodeList.add(node.getLeftNode());
                        if (node.getLeftNode().getLeftNode() != null || node.getLeftNode().getRightNode() != null) {
                            hasNextLevel = true;
                        }
                    }
                    if (node.getRightNode() != null) {
                        currentLevelNodeList.add(node.getRightNode());
                        if (node.getRightNode().getLeftNode() != null || node.getRightNode().getRightNode() != null) {
                            hasNextLevel = true;
                        }
                    }
                }
            }
            arrayList.add(currentLevelNodeList);
        }
        int[][] finalArray = new int[arrayList.size()][];
        for (int i = 0; i < arrayList.size(); i++) {
            ArrayList<TreeNode> currentList = arrayList.get(i);
            int[] currentArray = new int[currentList.size()];
            for (int j = 0; j < currentList.size(); j++) {
                currentArray[j] = currentList.get(j).getIndex();
            }
            finalArray[i] = currentArray;
        }
        return finalArray;
    }

}

class TreeNode {
    private int index;
    private TreeNode leftNode;
    private TreeNode rightNode;

    public TreeNode(int index) {
        this.index = index;
    }

    /**
     * 前序遍历
     *  1. 打印当前节点数值
     *  2. 若左树非空,递归左树
     *  3. 若右树非空,递归右树
     */
    public void preOrderTraversal() {
        // 1. 打印当前节点数值
        BinaryTree.orderList.add(this.index);
        System.out.print(this.index + " ");
        // 2. 若左树非空,递归左树
        if (this.leftNode != null) {
            this.leftNode.preOrderTraversal();
        }
        // 3. 若右树非空,递归右树
        if (this.rightNode != null){
            this.rightNode.preOrderTraversal();
        }
    }
    /**
     * 中序遍历
     *  1. 若左树非空,递归左树
     *  2. 打印当前节点数值
     *  3. 若右树非空,递归右树
     */
    public void infixOrderTraversal() {
        // 1. 若左树非空,递归左树
        if (this.leftNode != null) {
            this.leftNode.infixOrderTraversal();
        }
        // 2. 打印当前节点数值
        BinaryTree.orderList.add(this.index);
        System.out.print(this.index + " ");
        // 3. 若右树非空,递归右树
        if (this.rightNode != null) {
            this.rightNode.infixOrderTraversal();
        }
    }
    /**
     * 后序遍历
     *  1. 若左树非空,递归左树
     *  2. 若右树非空,递归右树
     *  3. 打印当前节点数值
     */
    public void postOrderTraversal() {
        // 1. 若左树非空,递归左树
        if (this.leftNode != null) {
            this.leftNode.postOrderTraversal();
        }
        // 2. 若右树非空,递归右树
        if (this.rightNode != null) {
            this.rightNode.postOrderTraversal();
        }
        BinaryTree.orderList.add(this.index);
        // 3. 打印当前节点数值
        System.out.print(this.index + " ");
    }

    /**
     * 前序查找
     * 1. 检查当前节点值,若与输入值相等,则返回当前节点
     * 2. 设置临时节点变量node,用于储存找到的节点(初始化为null)
     * 3. 查询左树
     * 3.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
     * 3.2 递归完成,若node非null,说明找到,返回node
     * 4. 查询右树
     * 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
     * 4.2 返回node(若node非空,则找到;否则未找到,返回null)
     *
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode preOrderSearch(int searchIndex) {
        // 1. 检查当前节点值,若与输入值相等,则返回当前节点
        if (this.index == searchIndex) {
            return this;
        }
        // 2. 设置临时节点变量node,用于储存找到的节点(初始化为null)
        TreeNode node = null;
        // 3. 查询左树
        // 3.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
        if (this.leftNode != null) {
            node = this.leftNode.preOrderSearch(searchIndex);
        }
        // 3.2 递归完成,若node非null,说明找到,返回node
        if (node != null) {
            return node;
        }
        // 4. 查询右树
        // 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
        if (this.rightNode != null) {
            node = this.rightNode.preOrderSearch(searchIndex);
        }
        // 4.2 返回node(若node非空,则找到;否则未找到,返回null)
        return node;
    }
    /**
     * 中序查找
     * 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
     * 2. 查询左树
     * 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
     * 2.2 递归完成,若node非null,说明找到,返回node
     * 3. 检查当前节点值,若与输入值相等,则返回当前节点
     * 4. 查询右树
     * 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
     * 4.2 返回node(若node非空,则找到;否则未找到,返回null)
     *
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode infixOrderSearch(int searchIndex) {
        // 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
        TreeNode node = null;
        // 2. 查询左树
        // 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
        if (this.leftNode != null) {
            node = this.leftNode.infixOrderSearch(searchIndex);
        }
        // 2.2 递归完成,若node非null,说明找到,返回node
        if (node != null) {
            return node;
        }
        // 3. 检查当前节点值,若与输入值相等,则返回当前节点
        if (this.index == searchIndex) {
            return this;
        }
        // 4. 查询右树
        // 4.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
        if (this.rightNode != null) {
            node = this.rightNode.infixOrderSearch(searchIndex);
        }
        // 4.2 返回node(若node非空,则找到;否则未找到,返回null)
        return node;
    }
    /**
     * 后序查找
     * 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
     * 2. 查询左树:
     * 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
     * 2.2 递归完成,若node非null,说明找到,返回node
     * 3. 查询右树
     * 3.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
     * 3.2 返回node(若node非空,则找到;否则未找到,返回null)
     * 4. 检查当前节点
     * 4.1 检查当前节点值,若与输入值相等,则返回当前节点
     * 4.2 否则,返回null
     *
     * @param searchIndex - 要查找的节点权重
     * @return - 找到则返回节点,未找到则返回null
     */
    public TreeNode postOrderSearch(int searchIndex) {
        // 1. 设置临时节点变量node,用于储存找到的节点(初始化为null)
        TreeNode node = null;
        // 2. 查询左树:
        // 2.1 若左树非空,递归左树,并将返回结果赋值给临时变量node
        if (this.leftNode != null) {
            node = this.leftNode.postOrderSearch(searchIndex);
        }
        // 2.2 递归完成,若node非null,说明找到,返回node
        if (node != null) {
            return node;
        }
        // 3. 查询右树
        // 3.1 若右树非空,递归右树,并将返回结果赋值给临时变量node
        if (this.rightNode != null) {
            node = this.rightNode.postOrderSearch(searchIndex);
        }
        // 3.2 递归完成,若node非null,说明找到,返回node
        if (node != null) {
            return node;
        }
        // 4. 检查当前节点
        // 4.1 检查当前节点值,若与输入值相等,则返回当前节点
        if (this.index == searchIndex) {
            return this;
        }
        // 4.2 否则,返回null
        return null;
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "index=" + index +
                '}';
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public TreeNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(TreeNode leftNode) {
        this.leftNode = leftNode;
    }

    public TreeNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(TreeNode rightNode) {
        this.rightNode = rightNode;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值