【数据结构】二叉树的Java实践

二叉树,是常用的树之一。

性质:

  • 每个节点最多有2个节点(即度最大为2)
  • 有左、右节点(或左、右子树)之分,且节点有顺序之分(即左、右不能随意调换)

下面对二叉树做最简单的Java实践。

> 二叉树的Java实践

树节点

package com.nicchagil.btree;

public class TreeNode {

    private Integer value;
    private TreeNode left;
    private TreeNode right;

    public TreeNode(Integer value) {
        super();
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    public TreeNode getLeft() {
        return left;
    }

    public void setLeft(TreeNode left) {
        this.left = left;
    }

    public TreeNode getRight() {
        return right;
    }

    public void setRight(TreeNode right) {
        this.right = right;
    }

}

二叉树

package com.nicchagil.btree;

/**
 * 二叉树
 */
public class BinaryTree {

    // 根节点
    private TreeNode root = null;

    /**
     * 插入节点
     */
    public boolean put(Integer value) {
        if (value == null) {
            return false;
        }

        if (root == null) {
            root = new TreeNode(value);
        }
        this.putNode(root, value);
        return true;
    }

    /**
     * 是否存在该值
     * @param value    值
     */
    public boolean contains(Integer value) {
        return scan(root, value);
    }

    private void putNode(TreeNode node, Integer value) {
        int result = this.compare(node.getValue(), value);

        /* 放左边 */
        if (result == 1) {
            if (node.getLeft() == null) {
                node.setLeft(new TreeNode(value));
            } else {
                this.putNode(node.getLeft(), value);
            }
        }
        /* 放右边 */
        else if (result == -1) {
            if (node.getRight() == null) {
                node.setRight(new TreeNode(value));
            } else {
                this.putNode(node.getRight(), value);
            }
        }
    }

    private boolean scan(TreeNode node, Integer value) {
        if (node == null) {
            return false;
        }

        int result = this.compare(node.getValue(), value);
        boolean remoteFlag = false;
        if (result == 0) {
            return true;
        } else if (result == 1) {
            remoteFlag = this.scan(node.getLeft(), value);
        } else {
            remoteFlag = this.scan(node.getRight(), value);
        }

        return remoteFlag;
    }

    public int compare(Integer nodeValue, Integer newValue) {
        return Integer.compare(nodeValue, newValue);
    }

    public TreeNode getRoot() {
        return root;
    }

}

> 打印二叉树。这是第一次写时犯的错误的示范。不删,以作借镜。重新写的见下文

(这是错误的,不删,以作借镜。重新写的见下文这个不是业务类,用于打印整棵树的形状的,就是查看树直观点

package com.nicchagil.btree;

import java.util.ArrayList;
import java.util.List;

public class BinaryTreePrinter {

    public static void print(BinaryTree bt) {
        if (bt == null || bt.getRoot() == null) {
            return;
        }

        List<StringBuffer> list = new ArrayList<StringBuffer>();

        /* 格式化根节点,及根节点左边树 */
        Integer level = 1;
        TreeNode node = bt.getRoot();
        StringBuffer sb = null;
        while (node != null) {
            sb = new StringBuffer();
            sb.append(node.getValue());
            list.add(sb);
            formatLeftDisplay(list, level, node.getValue());

            node = node.getLeft();
            level++;
        }

        /* 格式化根节点右边树 */
        level = 1;
        node = bt.getRoot();
        while (node != null) {
            if (node != bt.getRoot()) {
                formatRightDisplay(list, bt.getRoot(), level, node.getValue());
            }

            node = node.getRight();
            level++;
        }

        /* 将格式化好的数据打印出来 */
        for (StringBuffer temp : list) {
            System.out.println(temp);
        }
    }

    private static void formatLeftDisplay(List<StringBuffer> list, Integer level, Integer value) {
        if (list == null || list.size() == 0) {
            return;
        }

        String blank = replaceToBlank(value);

        for (int i = 0; i < level - 1; i++) {
            list.get(i).insert(0, blank);
        }
    }

    private static void formatRightDisplay(List<StringBuffer> list, TreeNode root, Integer level, Integer value) {
        if (list == null || list.size() == 0) {
            return;
        }

        Integer charCount = 0;
        Integer currentLevel = 2;
        TreeNode node = root.getLeft();
        while (currentLevel < level && node != null) {
            charCount += node.getValue().toString().length();
            node = node.getLeft();

            currentLevel++;
        }

        charCount += root.getValue().toString().length();

        currentLevel = 2;
        node = root.getRight();
        while (currentLevel < level && node != null) {
            charCount += node.getValue().toString().length();
            node = node.getRight();

            currentLevel++;
        }

        if (list.size() >= level) {
            list.get(level - 1).append(buildBlank(charCount)).append(value);
        } else {
            list.add(new StringBuffer().append(buildBlank(charCount)).append(value));
        }
    }

    private static String replaceToBlank(Integer value) {
        if (value == null) {
            return "";
        }
        return buildBlank(value.toString().length());
    }

    private static String buildBlank(int len) {
        StringBuffer sb = new StringBuffer();
        while (len != 0) {
            sb.append(" ");
            len--;
        }
        return sb.toString();
    }

}

测试类

package com.nicchagil.btree;

public class Call {

    public static void main(String[] args) {
        BinaryTree bt = new BinaryTree();
        bt.put(3);
        bt.put(2);
        bt.put(1);
        bt.put(4);
        bt.put(5);
        bt.put(-28);
        bt.put(35);
        bt.put(47);
        bt.put(50);
        bt.put(65);
        bt.put(-78);
        bt.put(91);
        bt.put(99);
        bt.put(-88);
        bt.put(75);
        bt.put(67);
        bt.put(70);
        bt.put(45);
        bt.put(-38);
        bt.put(21);

        System.out.println("binary tree -> ");
        BinaryTreePrinter.print(bt);

        System.out.println("whether contains -> " + bt.contains(47));
    }

}

(这是错误的,不删,以作借镜。重新写的见下文)日志

binary tree ->
           3
          2 4
         1   5
      -28     35
   -78          47
-88               50
                    65
                      91
                        99
whether contains -> true

> 将二叉树打印出来看看?

发现上述打印二叉树有致命的错误,看打印出来的日志就知道了,哈哈(>_<)

换种思路重新写打印类

package com.nicchagil.btree;

import java.util.HashMap;
import java.util.Map;

public class BinaryTreePrinter {

    /*
     * 程序会将tree数据转换成如下坐标
     * -n               0                n
     * ----------------------------------->
     *                  |
     *                  |
     *                  |
     *                  |
     *                  |
     *                  |
     *                  |
     *                  | h
     *                  v
     */

    private int leftIndexForX = 0; // 树最左节点的坐标,即-n
    private int rightIndexForX = 0; // 树最左节点的坐标,即n
    private int indexForY = 0; // 树最深节点的坐标,即h,正整数
    private Map<TreeNode, Index> map = new HashMap<TreeNode, Index>(); // key-树节点;value-x、y轴坐标

    public void print(BinaryTree bt) {
        if (bt == null || bt.getRoot() == null) {
            return;
        }

        // 根节点
        this.map.put(bt.getRoot(), new Index(0, 0));
        // 左边树遍历
        if (bt.getRoot().getLeft() != null) {
            this.getLeftest(bt.getRoot().getLeft(), -1, 1);
        }
        // 右边树遍历
        if (bt.getRoot().getRight() != null) {
            this.getRightest(bt.getRoot().getRight(), 1, 1);
        }

        /* 转换成数组 */
        int len = this.rightIndexForX - this.leftIndexForX;
        String[][] treeData = new String[this.indexForY + 1][len];

        int SHIFT = 0 - this.leftIndexForX;
        Index index = null;
        for (TreeNode node : this.map.keySet()) {
            index = this.map.get(node);

            treeData[index.getY()][SHIFT + index.getX()] = node.getValue().toString();
        }

        /* 将树以数组形式打印 */
        String[] treeRowData = null;
        String data = null;
        for (int i = 0; i < treeData.length; i++) {
            treeRowData = treeData[i];
            for (int j = 0; j < treeRowData.length; j++) {
                if (treeRowData[j] == null) {
                    data = "     ";
                } else {
                    data = this.fillBlankBeforeValue(treeRowData[j], 5);
                }
                System.out.print(data + " ");
            }

            /* 换两行树结构较明显 */
            System.out.println();
            System.out.println();
        }
    }

    /**
     * 设置最左、最深坐标
     */
    private synchronized void setMaxLeftHeightIndex(Index i) {
        if (i.getX() < leftIndexForX) {
            leftIndexForX = i.getX();
        }
        if (i.getY() > indexForY) {
            indexForY = i.getY();
        }
    }

    /**
     * 设置最右、最深坐标
     */
    private synchronized void setMaxRightHeightIndex(Index i) {
        if (i.getY() > rightIndexForX) {
            rightIndexForX = i.getY();
        }
        if (i.getY() > indexForY) {
            indexForY = i.getY();
        }
    }

    /**
     * 左边树遍历
     */
    private void getLeftest(TreeNode node, int xIndex, int yIndex) {
        Index i = new Index(xIndex, yIndex);
        map.put(node, i);

        if (node.getLeft() != null) {
            this.getLeftest(node.getLeft(), xIndex - 1, yIndex + 1);
        } else {
            this.setMaxLeftHeightIndex(i);
        }

        if (node.getRight() != null) {
            this.getLeftest(node.getRight(), xIndex + 1, yIndex + 1);
        }
    }

    /**
     * 右边树遍历
     */
    private void getRightest(TreeNode node, int xIndex, int yIndex) {
        Index i = new Index(xIndex, yIndex);
        map.put(node, new Index(xIndex, yIndex));

        if (node.getRight() != null) {
            this.getRightest(node.getRight(), xIndex + 1, yIndex + 1);
        } else {
            this.setMaxRightHeightIndex(i);
        }

        if (node.getLeft() != null) {
            this.getRightest(node.getLeft(), xIndex - 1, yIndex + 1);
        }
    }

    /**
     * 坐标类
     */
    class Index {
        int x;
        int y;

        public Index(int x, int y) {
            super();
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }

    /**
     * 前补空格
     */
    private String fillBlankBeforeValue(String v, int len) {
        StringBuffer sb = new StringBuffer();
        sb.append(v);
        while (sb.length() < len) {
            sb.insert(0, " ");
        }
        return sb.toString();
    }

}

测试类

package com.nicchagil.btree;

public class Call {

    public static void main(String[] args) {
        BinaryTree bt = new BinaryTree();
        bt.put(3);
        bt.put(2);
        bt.put(1);
        bt.put(4);
        bt.put(5);
        bt.put(-28);
        bt.put(35);
        bt.put(47);
        bt.put(50);
        bt.put(65);
        bt.put(-78);
        bt.put(91);
        bt.put(99);
        bt.put(-88);
        bt.put(75);
        bt.put(67);
        bt.put(70);
        bt.put(45);
        bt.put(-38);
        bt.put(21);

        System.out.println("binary tree -> ");
        new BinaryTreePrinter().print(bt);

        System.out.println("whether contains -> " + bt.contains(47));
    }

}

日志

binary tree ->
                                  3                                                       

                            2           4                                                 

                      1                       5                                           

              -28                                  35                                     

        -78                                  21          47                               

  -88         -38                                  45          50                         

                                                                     65                   

                                                                           91             

                                                                     75          99       

                                                               67                         

                                                                     70                   

whether contains -> true

时间: 2025-01-06 10:32:26

【数据结构】二叉树的Java实践的相关文章

【数据结构】之二叉树的java实现

二叉树的定义: 二叉树是树形结构的一个重要类型.许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要. 二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 这个定义是递归的.由于左.右子树也是二叉树, 因此子树也可为空树.下图中展现了五种不同基本形态的二叉树. 其中 (a) 为空树, (b

【数据结构与算法】二叉树的Java实现及特点总结

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加.但是他也有自己的缺点:删除操作复杂. 我们先介绍一些关于二叉树的概念名词. 二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树.二叉排序树.二叉搜索

【数据结构】二叉树的java实现

二叉树概述 数组.向量.链表都是一种顺序容器,它们提供了按位置访问数据的手段.而很多情况下,我们需要按数据的值来访问元素,而不是它们的位置来访问元素.比如有这样一个数组int num[3]={1,2,3},我们可以非常快速的访问数组中下标为2的数据,也就是说我们知道这个数据的位置,就可以快速访问.有时候我们是不知道元素的位置,但是却知道它的值是多少.假设我们有一个变量,存放在num这个数组中,我们知道它的值为2,却不知道它下标是多少,也就是说不知道它的位置.这个时候再去数组中访问这个元素就比较费

数据结构——二叉树遍历之“层遍历”

系列文章:数据结构与算法系列——从菜鸟到入门 层次遍历 二叉树的层次遍历是指,从二叉树的第一层(根结点)开始,从上至下逐层遍历,在同一层中从左至右依次遍历. 设置一个队列,将二叉树的根结点放入队列中. 将队列中的头结点出队,赋值给临时变量 temp,同时输出打印 temp.val. 判断 temp 是否有左结点和右结点,若有,分别将左.右结点放入队列中. 重复步骤 2~3,直至队列为空,表示二叉树的层次遍历结束. private static void cengci(TreeNode root)

二叉树的Java实现及特点总结

二叉树是一种非常重要的数据结构,它同时具有数组和链表各自的特点:它可以像数组一样快速查找,也可以像链表一样快速添加.但是他也有自己的缺点:删除操作复杂. 我们先介绍一些关于二叉树的概念名词. 二叉树:是每个结点最多有两个子树的有序树,在使用二叉树的时候,数据并不是随便插入到节点中的,一个节点的左子节点的关键值必须小于此节点,右子节点的关键值必须大于或者是等于此节点,所以又称二叉查找树.二叉排序树.二叉搜索树. 完全二叉树:若设二叉树的高度为h,除第 h 层外,其它各层 (1-h-1) 的结点数都

算法 《秦九韶算法java实践》

[历史背景] 秦九韶算法是中国南宋时期的数学家秦九韶表述求解一元高次多项式的值的算法--正负开方术.它也可以配合牛顿法用来求解一元高次多项式的根.在西方被称作霍纳算法(Horner algorithm或Horner scheme),是以英国数学家威廉·乔治·霍纳命名的. [原理解释] 设有n+1项的n次函数 f(x)=anxn+ an-1xn-1+an-2xn-2+ an-3xn-3+-- a2x2+a1x+ a0 将前n项提取公因子x,得 f(x)=(anxn-1+ an-1xn-2+an-2

关于java实践报告

关于java实践报告,总体来说并不是很难,对我而言最大的难度在于对集合的运用,这也说明了我对第七章甚至java的整体运用并不好,第七章因为不熟练的原因是因为代码量没有敲多少,很多东西并不理解,双列集合和单列集合的运用,一般而言,像这种银行系统肯定是用Map集合更好用,直接将用户账号设定为键值,将对象用户设置为value值,再对比账号密码时直接进行调用,不管是containsKey方法还是equals关键字比较都可以,使代码更灵活也更简单.而List集合虽然可以用,但用起来更加繁琐,且不说创建集合

数据结构二叉树——建立二叉树、中序递归遍历、非递归遍历、层次遍历

数据结构二叉树-- 编写函数实现:建立二叉树.中序递归遍历.借助栈实现中序非递归遍历.借助队列实现层次遍历.求高度.结点数.叶子数及交换左右子树. ("."表示空子树) #include<stdio.h> #include<stdlib.h> //***********二叉树链表节点结构 typedef char DataType; typedef struct Node {  DataType data;  struct Node*LChild;  struc

架构设计:系统间通信(5)——IO通信模型和JAVA实践 下篇

接上篇:<架构设计:系统间通信(4)--IO通信模型和JAVA实践 中篇>,我们继续讲解 异步IO 7.异步IO 上面两篇文章中,我们分别讲解了阻塞式同步IO.非阻塞式同步IO.多路复用IO 这三种IO模型,以及JAVA对于这三种IO模型的支持.重点说明了IO模型是由操作系统提供支持,且这三种IO模型都是同步IO,都是采用的"应用程序不询问我,我绝不会主动通知"的方式. 异步IO则是采用"订阅-通知"模式:即应用程序向操作系统注册IO监听,然后继续做自己