美文网首页
Java_二叉树概念及基本操作

Java_二叉树概念及基本操作

作者: 左上偏右 | 来源:发表于2016-12-24 12:43 被阅读72次

树、森林和二叉树的转换

  • 树转换为二叉树
  • 森林转换为树
  • 二叉树转换为树
  • 二叉树转换为森林
Paste_Image.png

代码

package com.self.data;

import java.util.ArrayList;
import java.util.Stack;

public class BinaryTree {
    private TreeNode root = null;

    public BinaryTree() {
        root = new TreeNode("A");
    }

 
     /** 
      * 构建二叉树 
      *              A 
      *         B         C 
      *     D      E    #   F 
      *   #   #  #   #    #   #  
      *   
      *   ABD##E##C#F##      
      */  
    public void createBinaryTree() {
        TreeNode nodeB = new TreeNode("B");
        TreeNode nodeC = new TreeNode("C");
        TreeNode nodeD = new TreeNode("D");
        TreeNode nodeE = new TreeNode("E");
        TreeNode nodeF = new TreeNode("F");
        root.leftChild = nodeB;
        root.rightChild = nodeC;
        nodeB.leftChild = nodeD;
        nodeB.rightChild = nodeE;
        nodeC.rightChild = nodeF;
    }
    
    /**
     * #方法创建二叉树
     * ABD##E##C#F##   
     *                                                               
     * @return
     */
    public void createTree(ArrayList<String> nodes){
        if (nodes==null || nodes.size()==0) {
            return;
        }
        createTree(nodes.size(), nodes);
    }
    public TreeNode createTree(int size,ArrayList<String> nodes){
        TreeNode treeNode = null;
        int index = size - nodes.size();
        String ch = nodes.get(0);
        if ("#".equals(ch)) {
            nodes.remove(0);
            return null;
        }
        treeNode = new TreeNode(index, ch);
        if (index==0) {
            //根结点
            root = treeNode;
        }
        nodes.remove(0);
        //创建左孩子
        treeNode.leftChild = createTree(size, nodes);
        //创建右孩子
        treeNode.rightChild = createTree(size, nodes);
        return treeNode;
    }
    

    /**
     * 求二叉树的高度
     * 
     * @author Administrator
     * 
     */
    public int getHeight() {
        return getHeight(root);
    }

    private int getHeight(TreeNode node) {
        if (node == null) {
            return 0;
        }

        int i = getHeight(node.leftChild);
        int j = getHeight(node.rightChild);
        return (i < j) ? j + 1 : i + 1;
    }

    /**
     * 获取二叉树的结点数
     * 
     * @author Administrator
     */
    public int getSize() {
        return getSize(root);
    }

    private int getSize(TreeNode node) {
        if (node == null) {
            return 0;
        } else {
            return 1 + getSize(node.leftChild) + getSize(node.rightChild);
        }
    }

    /**
     * 求二叉树的叶子节点 先计算左子树叶子节点,再计算右子树叶子节点
     * 
     * @return
     */
    public int getLeafSize() {
        return getLeafSize(root);
    }

    private int getLeafSize(TreeNode node) {
        int leafSize = 0;
        if (node == null) {
            return 0;
        }
        if (node.leftChild == null && node.rightChild == null) {
            leafSize++;
        }
        leafSize += getLeafSize(node.leftChild);
        leafSize += getLeafSize(node.rightChild);
        return leafSize;
    }

    /**
     * 找二叉树最左边的孩子节点
     * 
     * @return
     */

    private TreeNode getLeftMostNode(TreeNode node, Stack<TreeNode> stack) {
        if (node == null) {
            return null;
        }
        while (node.leftChild != null) {
            stack.push(node);
            node = node.leftChild;
        }
        return node;
    }
    
    /**
     * 后续遍历 - 非递归 
     * 步骤1  如果结点有左子树,该结点入栈; 如果结点没有左子树,访问该结点; 
     * 步骤2  如果结点有右子树,重复
     * 步骤3  如果结点没有右子树(结点访问完毕),根据栈顶指示回退,访问栈顶元素,
     *     并访问右子树,重复步骤 如果栈为空,表示遍历结束。
     */
    public void nonPostOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = getLeftMostNode(node, stack);
        while (treeNode != null) {
            System.out.println("nonRecOrderdata" + treeNode.getData());
            if (treeNode.rightChild != null) {
                treeNode = getLeftMostNode(treeNode.rightChild, stack);
            } else if (!stack.isEmpty()) {
                treeNode = stack.pop();
            } else {
                treeNode = null;
            }
        }
    }
    /**
     * 中续遍历 - 非递归 
     * 1、让做孩子循环进栈,当没有左孩子退出,执行出栈。
     * 2、获取刚出栈的结点,为空时出栈并处理右子树,不为空循环1,2。
     */
    
    public void nonMidOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode root = node;
        while (root != null || !stack.isEmpty()) {
            while (root != null) {
                stack.push(root);// 先访问再入栈
                root = root.leftChild;
            }
            root = stack.pop();
            System.out.println("nonRecOrderdata " + root.getData());
            root = root.rightChild;// 如果是null,出栈并处理右子树
        }
    }

    /**
     * 前序遍历——迭代
     * 
     * @author Administrator
     * 
     */
    public void preOrder(TreeNode node) {
        if (node == null) {
            return;
        } else {
            System.out.println("preOrder data:" + node.getData());
            preOrder(node.leftChild);
            preOrder(node.rightChild);
        }
    }

    /**
     * 前序遍历——非迭代 需要借助栈模式进行操作
     */
    public void nonRecOrder(TreeNode node) {
        if (node == null) {
            return;
        }
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.push(node);
        while (!stack.isEmpty()) {
            // 出栈和进栈
            TreeNode n = stack.pop();// 弹出根结点
            // 压入子结点
            System.out.println("nonRecOrder data" + n.getData());
            if (n.rightChild != null) {
                stack.push(n.rightChild);

            }
            if (n.leftChild != null) {
                stack.push(n.leftChild);
            }
        }
    }

    /**
     * 中序遍历——迭代
     * 
     * @author Administrator
     * 
     */
    public void midOrder(TreeNode node) {
        if (node == null) {
            return;
        } else {
            midOrder(node.leftChild);
            System.out.println("midOrder data:" + node.getData());
            midOrder(node.rightChild);
        }
    }

    /**
     * 后序遍历——迭代
     * 
     * @author Administrator
     * 
     */
    public void postOrder(TreeNode node) {
        if (node == null) {
            return;
        } else {
            postOrder(node.leftChild);
            postOrder(node.rightChild);
            System.out.println("postOrder data:" + node.getData());
        }
    }

    public class TreeNode {
        private int index;
        private String data;
        private TreeNode leftChild;
        private TreeNode rightChild;

        public int getIndex() {
            return index;
        }

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

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }

        public TreeNode(int index, String data) {
            this.index = index;
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
        }

        public TreeNode(String data) {
            this.data = data;
            this.leftChild = null;
            this.rightChild = null;
        }
    }

/**
 * 层次遍历方法1
 * 首先把第0层保存在一个队列中,然后按节点访问,并把已经访问节点的左右孩子节点放在第二个队列中,当第一个队
 * 列中的所有节点都访问完成之后,交换两个节点。这样重复下去,知道所有层的节点都被访问,这样做的代价就是空间复杂度有点高。
 */
private void broadLevelTree() {
    LinkedList<TreeNode> linkedList = new LinkedList<BinaryTree.TreeNode>();
    LinkedList<TreeNode> secondList = new LinkedList<BinaryTree.TreeNode>();
    linkedList.add(root);
    System.out.println("层次遍历:");
    TreeNode tmpRoot = null;
    while (!linkedList.isEmpty()) {//层次
        while (!linkedList.isEmpty()) {//某一层的所有孩子结点
            tmpRoot = linkedList.removeFirst();
            System.out.print(" " + tmpRoot.data);
            if (tmpRoot.leftChild != null) {
                secondList.add(tmpRoot.leftChild);
            }
            if (tmpRoot.rightChild != null) {
                secondList.add(tmpRoot.rightChild);
            }
        }
        linkedList.addAll(secondList);
        secondList.clear();
    }

}

/**
 * 层次遍历方法2
 * 递归遍历,遍历某一层的数据,想要遍历整个树,对层次进行for循环
 * 
 * @param node
 *            起始结点为根结点
 * @param level
 *            第几层
 * @return
 */
private int broadLevelTree(TreeNode node, int level) {
    if (node == null) {
        return 0;
    }
    if (level == 0) {
        System.out.println("层次遍历: " + node.data);
        return 1;
    }
    return broadLevelTree(node.leftChild, level - 1)
            + broadLevelTree(node.rightChild, level - 1);
}

    public static void main(String[] args) {
        BinaryTree binaryTree = new BinaryTree();
//      binaryTree.createBinaryTree();
        
        String[] nodes = new String[]{"A","B","D","#","#","E","#","#","C",
                "#","F","#","#"};
        ArrayList<String> listNodes = new ArrayList<String>();
        for (int i = 0; i < nodes.length; i++) {
            listNodes.add(nodes[i]);
        }
        binaryTree.createTree(listNodes);
        
        int height = binaryTree.getHeight();
        System.out.println("treeHeihgt:" + height);
        int size = binaryTree.getSize();
        System.out.println("treeSize:" + size);
        int leafSize = binaryTree.getLeafSize();
        System.out.println("leafSize:" + leafSize);

        System.out.println("前序遍历:");
        binaryTree.preOrder(binaryTree.root);
        System.out.println("中序遍历:");
        binaryTree.midOrder(binaryTree.root);
        System.out.println("后序遍历:");
        binaryTree.postOrder(binaryTree.root);
        System.out.println("非递归遍历:");
        binaryTree.nonRecOrder(binaryTree.root);
        System.out.println("非递归中序遍历:");
        binaryTree.nonMidOrder(binaryTree.root);
        System.out.println("非递归后续遍历:");
        binaryTree.nonPostOrder(binaryTree.root);

        for (int i = 0; i < 3; i++) {
            binaryTree.broadLevelTree(binaryTree.root, i);
        }
        binaryTree.broadLevelTree();
    }

}

相关文章

  • Java_二叉树概念及基本操作

    树、森林和二叉树的转换 树转换为二叉树 森林转换为树 二叉树转换为树 二叉树转换为森林 代码

  • 基本概念及操作

    Linux桌面环境介绍 相对于现在的Windows系统,UNIX/Linux系统本身是没有图形界面的。通常在UNI...

  • 基本概念及操作

    1、linux桌面环境介绍 linux本身没有图形界面,我们所看到的实际是运行在linux系统之上的一套软件。li...

  • 基本概念及操作

    1、Linux本身没有图形界面,我们所看到的图形界面,都是安装在Linux中的一套软件。 2、用户通过终端模拟器操...

  • 基本概念及操作

    本节先介绍了Linux的桌面环境,运行在Linux上的图形界面为运行在Linux上的软件,Linux的此款软件现在...

  • 基本概念及操作

    一、 Linux 桌面环境介绍相对于现在的 Windows 系统,UNIX/Linux 本身是没有图形界面的,我们...

  • 基本概念及操作

    UNIX/Linux 本身是没有图形界面的,在 UNIX/Linux 发行版上看到的图形界面实际都只是运行在 Li...

  • ElasticSearch 02 与SpringBoot2.x集

    ElasticSearch 01 基础概念及基本操作 ElasticSearch 02 与SpringBoot2....

  • ElasticSearch 03 全文检索

    ElasticSearch 01 基础概念及基本操作 ElasticSearch 02 与SpringBoot2....

  • ElasticSearch 01 基础概念及基本操作

    ElasticSearch 01 基础概念及基本操作 ElasticSearch 02 与SpringBoot2....

网友评论

    本文标题:Java_二叉树概念及基本操作

    本文链接:https://www.haomeiwen.com/subject/aqblvttx.html