二叉树,是常用的树之一。
性质:
- 每个节点最多有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