package com.java.study.datastructuresalgorithms.basisdatastructure.tree; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingDeque; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 实现自己的二叉树 * 链式二叉树,使用顺序存储结构 * * @author Mr.Xu * @date 2020/4/4 12:50 */ @Data @Accessors(chain = true) @AllArgsConstructor @NoArgsConstructor public class XbSequenceBinaryTree<T> { /* 我们把根节点存储在下标 i = 1 的位置, 那左子节点存储在下标 2 * i = 2 的位置, 右子节点存储在 2 * i + 1 = 3 的位置。 以此类推,B 节点的左子节点存储在 2 * i = 2 * 2 = 4 的位置, 右子节点存储在 2 * i + 1 = 2 * 2 + 1 = 5 的位置。 */ private T[] data; private int height; /** * 使用一组数据构建一个完全二叉树 * * @param t 原始数据 * @return */ public static <T> XbSequenceBinaryTree<T> build(T[] t) { /* 求以2为底,t.length的对数,再向上取整即为高度 */ double log2 = Math.log(t.length + 1) / Math.log(2); int height = (int) Math.ceil(log2) - 1; Object[] dataT = new Object[t.length + 1]; System.arraycopy(t, 0, dataT, 1, t.length); return new XbSequenceBinaryTree<>((T[]) dataT, height); } public String prettyToString(int unitCharsLength) { /* 单个字符的组成方式 */ String unitChars = Stream.generate(()->" ").limit(unitCharsLength).collect(Collectors.joining()); /* 计算每一行最大需要的字符数 */ String lineString = Stream.generate(() -> unitChars).limit((int) Math.pow(2, this.height + 2)).collect(Collectors.joining()); Stream.Builder<String> builder = Stream.builder(); /* 广度优先遍历二叉树,即一行一行遍历 */ for (int i = this.height; i >= 0; i--) { /* 计算左边距离 */ int leftLen = (int) Math.pow(2, i); /* 计算元素之间的距离 */ int stepLen = leftLen * 2; StringBuffer lineStringBuffer = new StringBuffer(lineString); /* 每一行的元素个数 */ int lineCount = (int) Math.pow(2, this.height - i); /* 每一行元素开始 和 结束的下边 */ int lineStartIndex = lineCount; int lineEndIndex = Math.min(lineStartIndex + lineCount - 1, this.data.length - 1); /* 当前元素是这一行中的第几个元素 */ int lineIndex = 0; for (int j = lineStartIndex; j <= lineEndIndex; j++) { lineIndex++; T s = this.data[j]; if (s == null) { continue; } else { String stringData = s.toString(); /* 计算此元素在这一行中是第几个元素,按照满二叉树计算 即: null ,null , 2 ,3 ,则, 3 是第四个元素 */ /* 计算这个元素的首个字符在这一行内是第几个位置 */ int start = ((lineIndex - 1) * stepLen + leftLen) * unitChars.length(); lineStringBuffer.replace(start, start + stringData.length(), stringData); } } builder.add(lineStringBuffer.toString()).add("\n"); } return builder.build().collect(Collectors.joining()); } /** * 广度优先遍历 */ public List<T> bfsTraversal() { ArrayList<T> list = new ArrayList<>(); LinkedBlockingDeque<Integer> queue = new LinkedBlockingDeque<>(); if (data.length > 1) { queue.add(1); } int lenFromRoot = 0; while (!queue.isEmpty()) { int size = queue.size(); System.out.print("距离根节点的距离 = " + (lenFromRoot++) + " element = ["); Stream.generate(() -> queue.poll()).limit(size).forEach(index -> { System.out.print(" " + data[index] + " "); int leftNodeIndex = index * 2; if (data.length > (leftNodeIndex) && data[leftNodeIndex] != null) { queue.add(leftNodeIndex); } int rightNodeIndex = index * 2 + 1; if (data.length > (rightNodeIndex) && data[rightNodeIndex] != null) { queue.add(rightNodeIndex); } }); System.out.println("]\n"); } return list; } public static void main(String[] args) { Integer[] objects = Stream.iterate(1, i -> i + 1).limit(31).toArray(Integer[]::new); XbSequenceBinaryTree<Integer> build = XbSequenceBinaryTree.build(objects); System.out.println(build.prettyToString(3)); build.bfsTraversal(); System.out.println(build); } }
java控制台输出二叉树(二叉树使用数组结构存储)
最新推荐文章于 2022-09-15 09:43:24 发布