二叉树相关算法——创建、遍历、求深度和广度

二叉树相关的算法,遍历使用了递归和迭代两种算法,可作为结果对比。
理解起来不难,直接上代码,有空再补下注释说明原理。

package com.junyang.algodemo.Tree;

import java.util.LinkedList;
import java.util.Stack;

public class TreeUtil {
    private static final int DEEP = 5;

    /* 创建一个深度为deep的满二叉树,目的是为验证其它算法 */
    public static TreeNode createTree(int deep) {
        /* 处理deep为0 和为1的特殊情况 */
        if (0 >= deep) {
            return null;
        }

        int count = 0;
        TreeNode root = new TreeNode(count++);
        if (1 == deep) {
            return root;
        }

        /* 满二叉树创建完成的条件为,当前这一层达到2的 deep-1 次方 */
        double maxLayerNum = Math.pow(2f, deep - 1f);

        TreeNode last = root;

        /* 通过队列按层创建二叉树 */
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int width = 0;

        while (!queue.isEmpty()) {
            TreeNode temp = queue.remove();
            temp.left = new TreeNode(count++);
            temp.right = new TreeNode(count++);

            queue.add(temp.left);
            queue.add(temp.right);
            width += 2;

            if (width == maxLayerNum) {
                return root;
            }

            if (temp == last) {
                last = last.right;
                width = 0;
            }
        }

        return root;
    }

    /* 按层遍历同時按行显示 */
    public static void printTreeForLayer(TreeNode root) {
        if (null == root) {
            return;
        }

        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        TreeNode last = root;
        TreeNode nlast = root;
        int lineNum = 1;

        System.out.print("num[" + lineNum++ + "]:");
        while (!queue.isEmpty()) {
            TreeNode temp = queue.remove();

            if (null != temp.left) {
                queue.add(temp.left);
                nlast = temp.left;
            }

            if (null != temp.right) {
                queue.add(temp.right);
                nlast = temp.right;
            }

            System.out.print(temp.data + " ");
            if (temp == last) {
                System.out.println();
                if (!queue.isEmpty()) {
                    System.out.print("num[" + lineNum++ + "]:");
                }
                last = nlast;
            }
        }
    }

    /* 先序遍历 —— 递归 */
    public static void printTreeForRootFirst1(TreeNode root) {
        if (root == null) {
            return;
        }

        System.out.print(root.data + " ");
        printTreeForRootFirst1(root.left);
        printTreeForRootFirst1(root.right);

    }

    /* 先序遍历 —— 迭代*/
    public static void printTreeForRootFirst2(TreeNode root) {
        if (null == root) {
            return;
        }

        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);

        while (!stack.isEmpty()) {
            TreeNode top = stack.pop();
            System.out.print(top.data + " ");

            if (top.right != null) {
                stack.push(top.right);
            }

            if (top.left != null) {
                stack.push(top.left);
            }
        }
    }


    /* 中序遍历 —— 递归 */
    public static void printTreeForRootMiddle(TreeNode root) {
        if (root == null) {
            return;
        }

        printTreeForRootMiddle(root.left);
        System.out.print(root.data + " ");
        printTreeForRootMiddle(root.right);

    }

    /* 中序遍历 —— 迭代 */
    public static void printTreeForRootMiddle2(TreeNode root) {
        if (root == null) {
            return;
        }

        Stack<TreeNode> stack = new Stack<>();

        TreeNode cur = root;
        while (!stack.isEmpty() || cur != null) {
            if (cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();
                System.out.print(cur.data + " ");
                cur = cur.right;
            }
        }
    }

    /* 后序遍历 —— 递归 */
    public static void printTreeForRootLast(TreeNode root) {
        if (root == null) {
            return;
        }

        printTreeForRootLast(root.left);
        printTreeForRootLast(root.right);
        System.out.print(root.data + " ");

    }

    /* 后序遍历 —— 迭代 */
    public static void printTreeForRootLast2(TreeNode root) {
        if (root == null) {
            return;
        }

        Stack<TreeNode> stack = new Stack<>();
        Stack<TreeNode> output = new Stack<>();

        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode temp = stack.pop();
            output.push(temp);

            if (null != temp.left) {
                stack.push(temp.left);
            }

            if (null != temp.right) {
                stack.push(temp.right);
            }
        }

        while (!output.isEmpty()) {
            System.out.print(output.pop().data + " ");
        }
    }

    /* 获取二叉树的宽度 */
    public static int getWidth(TreeNode root) {
        if (null == root) {
            return 0;
        }

        int maxWidth = 1;
        int curWidth = 0;
        LinkedList<TreeNode> linkedList = new LinkedList<>();
        linkedList.add(root);

        TreeNode last = root;
        TreeNode nlast = root;
        while (!linkedList.isEmpty()) {
            TreeNode temp = linkedList.remove();

            if (null != temp.left) {
                linkedList.add(temp.left);
                nlast = temp.left;
                curWidth++;
            }

            if (null != temp.right) {
                linkedList.add(temp.right);
                nlast = temp.right;
                curWidth++;
            }

            if (temp == last) {
                last = nlast;
                maxWidth = maxWidth > curWidth ? maxWidth : curWidth;
                curWidth = 0;
            }
        }

        return maxWidth;
    }

    /* 获取二叉树的深度 */
    public static int getDeep(TreeNode root) {
        if (null == root) {
            return 0;
        }

        int leftDeep = 0;
        if (root.left != null) {
            leftDeep = getDeep(root.left);
        }

        int rightDeep = 0;
        if (root.right != null) {
            rightDeep = getDeep(root.right);
        }

        return (rightDeep > leftDeep ? rightDeep : leftDeep) + 1;
    }

    public static void main(String[] args) {
        TreeNode root = createTree(DEEP);
        System.out.println("按层遍历");
        printTreeForLayer(root);

        System.out.println("先序遍历");
        printTreeForRootFirst1(root);
        System.out.println();
        printTreeForRootFirst2(root);
        System.out.println();

        System.out.println("中序遍历");
        printTreeForRootMiddle(root);
        System.out.println();
        printTreeForRootMiddle2(root);
        System.out.println();

        System.out.println("后序遍历");
        printTreeForRootLast(root);
        System.out.println();
        printTreeForRootLast2(root);
        System.out.println();

        System.out.println("deep:" + getDeep(root));
        System.out.println("width:" + getWidth(root));
    }
}

输出:

按层遍历
num[1]:0 
num[2]:1 2 
num[3]:3 4 5 6 
num[4]:7 8 9 10 11 12 13 14 
num[5]:15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
先序遍历
0 1 3 7 15 16 8 17 18 4 9 19 20 10 21 22 2 5 11 23 24 12 25 26 6 13 27 28 14 29 30 
0 1 3 7 15 16 8 17 18 4 9 19 20 10 21 22 2 5 11 23 24 12 25 26 6 13 27 28 14 29 30 
中序遍历
15 7 16 3 17 8 18 1 19 9 20 4 21 10 22 0 23 11 24 5 25 12 26 2 27 13 28 6 29 14 30 
15 7 16 3 17 8 18 1 19 9 20 4 21 10 22 0 23 11 24 5 25 12 26 2 27 13 28 6 29 14 30 
后序遍历
15 16 7 17 18 8 3 19 20 9 21 22 10 4 1 23 24 11 25 26 12 5 27 28 13 29 30 14 6 2 0 
15 16 7 17 18 8 3 19 20 9 21 22 10 4 1 23 24 11 25 26 12 5 27 28 13 29 30 14 6 2 0 
deep:5
width:16
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树深度遍历广度遍历是常用的遍历算法深度遍历是指对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。深度遍历可以细分为先序遍历、中序遍历和后序遍历。先序遍历是先访问根节点,然后递归地先序遍历左子树,再递归地先序遍历右子树。中序遍历是先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树。后序遍历是先递归地后序遍历左子树,然后递归地后序遍历右子树,最后访问根节点。\[2\] 广度遍历是按层次遍历二叉树,先访问根节点,然后依次访问每一层的节点。广度遍历可以通过使用队列来实现。首先将根节点入队,然后循环执行以下步骤:出队一个节点,访问该节点,将该节点的左右子节点入队。直到队列为空。\[1\] 所以,二叉树深度遍历广度遍历是不同的遍历方式,深度遍历是递归地探索子树,而广度遍历是按层次遍历节点。这两种遍历方式在不同的场景下有不同的应用。 #### 引用[.reference_title] - *1* [二叉树深度遍历广度遍历](https://blog.csdn.net/weixin_37901561/article/details/105499250)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [二叉树(一):深度优先遍历广度优先遍历](https://blog.csdn.net/Mike_honor/article/details/125828311)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值