zoukankan      html  css  js  c++  java
  • 【数据结构】之二叉树(Java语言描述)

      有关树的一些基础知识点请参考【这篇文章】。

      本文主要记录Java语言描述的二叉树相关的一些操作,如创建、遍历等。

      首先,我们需要一个表示树中节点的数据结构TreeNode,代码如下:

    public class TreeNode<T> {
        public T data;
        public TreeNode<T> lChild;
        public TreeNode<T> rChild;
        public TreeNode<T> parent;
    
        public TreeNode() {
        }
    
        public TreeNode(T data) {
            this.data = data;
            this.lChild = null;
            this.rChild = null;
            this.parent = null;
        }
    
        public TreeNode(T data, TreeNode<T> parent, boolean isLeftC) {
            this.data = data;
            this.parent = parent;
            if (isLeftC) {
                parent.lChild = this;
            } else {
                parent.rChild = this;
            }
        }
    }

      在二叉树的工具类BinaryTree中,提供了很多的方法,详细介绍如下:

    (1)创建二叉树的时候,通过传入的字符串来自动生成二叉树的结构。注意:字符串是前序遍历的结构,每个节点都有左右两个节点,如果某个节点为空,则用“#”符号表示;节点与节点之间用空格隔开。

    (2)使用递归和非递归的方式进行二叉树的前、中、后序遍历的方法。

    (3)对二叉树进行层序遍历的方法。

    (4)获取树的深度和树中节点总数的方法。

      以下是BinaryTree类中的详细代码:

    public class BinaryTree {
        private TreeNode<String> root;
        private int size;
    
        // 根据初始化字符串生成二叉树
        public BinaryTree(String content) {
            root = createBTree(new Scanner(content));
        }
    
        // 直接将一棵TreeNode树赋值为二叉树
        public BinaryTree(TreeNode<String> root) {
            this.root = root;
        }
    
        // 根据字符串创建二叉树
        private TreeNode<String> createBTree(Scanner scanner) {
            String data = scanner.next();
            if ("#".equals(data)) return null;
            TreeNode<String> node = new TreeNode<>(data);
            size++;
            node.lChild = createBTree(scanner);
            node.rChild = createBTree(scanner);
            return node;
        }
    
        // 获取二叉树的深度
        public int getBTreeDepth() {
            return getBTreeDepth(root);
        }
    
        private int getBTreeDepth(TreeNode root) {
            return root == null ? 0 : Math.max(getBTreeDepth(root.lChild), getBTreeDepth(root.rChild)) + 1;
        }
    
        // 返回二叉树中节点个数
        public int size() {
            return size;
        }
    
        // 前序遍历二叉树(useRec:是否使用递归方式)
        public void traverseBefore(boolean useRec) {
            if (useRec) {
                traverseBeforeRec(root);
            } else {
                traverseBeforeNonRec();
            }
        }
    
        // 前序遍历二叉树(递归)
        private void traverseBeforeRec(TreeNode node) {
            if (node == null) {
                System.out.print("#");
            } else {
                System.out.print(node.data);
                traverseBeforeRec(node.lChild);
                traverseBeforeRec(node.rChild);
            }
        }
    
        // 前序遍历二叉树(非递归)
        private void traverseBeforeNonRec() {
            Stack<TreeNode<String>> stack = new Stack<>();
            TreeNode<String> currRoot = root;
            while (true) {
                if (currRoot != null) {
                    System.out.print(currRoot.data);
                    stack.push(currRoot.rChild);
                    currRoot = currRoot.lChild;
                } else {
                    System.out.print("#");
                    if (stack.size() == 0) break;
                    currRoot = stack.pop();
                }
            }
        }
    
        // 中序遍历二叉树
        public void traverseMiddle(boolean useRec) {
            if (useRec) {
                traverseMiddleRec(root);
            } else {
                traverseMiddleNonRec();
            }
        }
    
        // 中序遍历二叉树(递归)
        private void traverseMiddleRec(TreeNode node) {
            if (node == null) {
                System.out.print("#");
            } else {
                traverseMiddleRec(node.lChild);
                System.out.print(node.data);
                traverseMiddleRec(node.rChild);
            }
        }
    
        // 中序遍历二叉树(非递归)
        private void traverseMiddleNonRec() {
            Stack<TreeNode<String>> stack = new Stack<>();
            TreeNode<String> currRoot = root;
            while (true) {
                if (currRoot != null) {
                    stack.push(currRoot);
                    currRoot = currRoot.lChild;
                } else {
                    System.out.print("#");
                    if (stack.size() == 0) break;
                    TreeNode<String> middleNode = stack.pop();
                    System.out.print(middleNode.data);
                    currRoot = middleNode.rChild;
                }
            }
        }
    
        // 后序遍历二叉树
        public void traverseAfter(boolean useRec) {
            if (useRec) {
                traverseAfterRec(root);
            } else {
                traverseAfterNonRec();
            }
        }
    
        // 后序遍历二叉树(递归)
        private void traverseAfterRec(TreeNode node) {
            if (node == null) {
                System.out.print("#");
            } else {
                traverseAfterRec(node.lChild);
                traverseAfterRec(node.rChild);
                System.out.print(node.data);
            }
        }
    
        // 后序遍历二叉树(非递归)
        private void traverseAfterNonRec() {
            Stack<TreeNode<String>> stack = new Stack<>();
            TreeNode<String> lastNode = null;
            TreeNode<String> currRoot = root;
            while (true) {
                if (currRoot != null) {
                    if (lastNode != null && currRoot.rChild == lastNode) {
                        System.out.print(currRoot.data);
                        lastNode = currRoot;
                        currRoot = stack.peek().rChild;
                        if (root.rChild == currRoot && currRoot == lastNode) {
                            System.out.print(root.data);
                            break;
                        }
                    } else if (lastNode != null && currRoot.lChild == lastNode) {
                        if (currRoot.rChild == null) {
                            System.out.print("#" + currRoot.data);
                            lastNode = currRoot;
                            currRoot = stack.pop();
                        }
                    } else {
                        stack.push(currRoot);
                        currRoot = currRoot.lChild;
                    }
                } else {
                    System.out.print("#");
                    currRoot = stack.peek().rChild;
                    if (currRoot == null) {
                        System.out.print("#");
                        lastNode = stack.pop();
                        System.out.print(lastNode.data);
                        currRoot = stack.pop();
                    }
                }
            }
        }
    
        // 层序遍历二叉树
        public void traverseCeng() {
            Queue<TreeNode> queue = new LinkedList<>();
            queue.offer(root);
            while (!queue.isEmpty()) {
                TreeNode node = queue.poll();
                if (node == null) {
                    System.out.print("#");
                } else {
                    System.out.print(node.data);
                    queue.offer(node.lChild);
                    queue.offer(node.rChild);
                }
            }
        }
    }

      测试类代码:

    public class TestTree {
        private static final String TREE_CONTENT = "A B D # G # # E # # C # F H # # #";
    
        public static void main(String args[]) {
            System.out.println("根据字符串" + TREE_CONTENT + "生成二叉树");
            BinaryTree bTree = new BinaryTree(TREE_CONTENT);
    
            System.out.print("二叉树前序遍历结果:");
            bTree.traverseBefore(false);
    
            System.out.print("
    二叉树中序遍历结果:");
            bTree.traverseMiddle(false);
    
            System.out.print("
    二叉树后序遍历结果:");
            bTree.traverseAfter(false);
    
            System.out.print("
    二叉树层序遍历结果:");
            bTree.traverseCeng();
    
            System.out.println("
    二叉树深度:" + bTree.getBTreeDepth());
    
            System.out.println("二叉树中节点个数:" + bTree.size());
        }
    }

      运行结果:

    根据字符串A B D # G # # E # # C # F H # # #生成二叉树
    二叉树前序遍历结果:ABD#G##E##C#FH###
    二叉树中序遍历结果:#D#G#B#E#A#C#H#F#
    二叉树后序遍历结果:###G##E###HFC
    二叉树层序遍历结果:ABCDE#F#G##H#####
    二叉树深度:4
    二叉树中节点个数:8
  • 相关阅读:
    docker常用软件安装及使用
    生成base64位图片验证码
    项目经理的特殊需求,对象的移动,
    集成微信支付的代码。兼容小程序,扫码,app,公众号。h5 支付 ,以及 服务商提现
    nginx请求转发配置
    nginx的conf文件,两种配置方式,第一种无ssl证书,第二种有ssl证书。
    Springboot集成WebSocket通信全部代码,即扣即用。
    Centos7上安装docker
    mysql 5.7 的 /etc/my.cnf
    【图嵌入】DeepWalk 和 Node2Vec
  • 原文地址:https://www.cnblogs.com/itgungnir/p/7376036.html
Copyright © 2011-2022 走看看