package com.java.study.datastructuresalgorithms.basisdatastructure.tree;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.RandomUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 實現自己的二叉樹
* 鏈式二叉樹,使用鏈式結構存儲數據
*
* @author Mr.Xu
* @date 2020/4/1 21:50
*/
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class XbLinkedBinaryTree<T> {
private XbLinkedBinaryTree<T> leftNode;
private T data;
private XbLinkedBinaryTree<T> rightNode;
/**
* 深度 : 根節點到這個節點所經歷的邊的個數
* 從上先下遞增,根節點深度爲0
*/
private int depth;
/**
* 層 : 節點的深度 + 1
*/
private int level;
/**
* 高度 : 節點到葉子節點的最長路徑(邊數)
* 從下向上遞增,最下面高度爲0
*/
private int height;
/**
* 若使用數組存儲二叉樹時,此元素在數組中位置的下標
*/
private int index;
/**
* 使用一組數據隨機的構建一個二叉樹
*
* @param t 原始數據
* @return
*/
public static <T> XbLinkedBinaryTree<T> build(T[] t) {
XbLinkedBinaryTree result = null;
if (t.length > 0) {
result = XbLinkedBinaryTree.build(0, t.length - 1, t, 0, 1);
}
return result;
}
private static <T> XbLinkedBinaryTree<T> build(int left, int right, T[] t, int depth, int index) {
XbLinkedBinaryTree result = null;
int length = right - left;
if (length >= 0) {
/* 選擇此節點的數據索引位置 */
int pickNumber = RandomUtils.nextInt(left, right + 1);
XbLinkedBinaryTree<T> leftTree = XbLinkedBinaryTree.build(left, pickNumber - 1, t, (depth + 1), index * 2);
XbLinkedBinaryTree<T> rightTree = XbLinkedBinaryTree.build(pickNumber + 1, right, t, (depth + 1), (index * 2 + 1));
int leftTreeHeight = leftTree == null ? 0 : leftTree.getHeight() + 1;
int rightTreeHeight = rightTree == null ? 0 : rightTree.getHeight() + 1;
result = new XbLinkedBinaryTree(leftTree, t[pickNumber], rightTree, depth, (++depth), Math.max(leftTreeHeight, rightTreeHeight), index);
}
return result;
}
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());
/* 把二叉樹按層打印出來 */
List<XbLinkedBinaryTree<T>> dataList = new ArrayList();
dataList.add(this);
Stream.Builder<String> builder = Stream.builder();
Optional<XbLinkedBinaryTree<T>> any;
while ((any = dataList.stream().findAny()).isPresent()) {
int currentNodeHeight = this.getHeight()-any.get().getDepth();
int leftLen = (int) Math.pow(2, currentNodeHeight);
int stepLen = leftLen * 2;
StringBuffer lineStringBuffer = new StringBuffer(lineString);
int upLevelCount = (int) Math.pow(2, any.get().getDepth()) - 1;
dataList = dataList.stream().flatMap(s -> {
String stringData = s.getData().toString();
/* 計算此元素在這一行中是第幾個元素,按照滿二叉樹計算 即: null ,null , 2 ,3 ,則, 3 是第四個元素 */
int lineIndex = s.getIndex() - upLevelCount;
/* 計算這個元素的首個字符在這一行內是第幾個位置 */
int start = ((lineIndex - 1) * stepLen + leftLen) * unitChars.length();
lineStringBuffer.replace(start, start + stringData.length(), stringData);
Stream<XbLinkedBinaryTree<T>> nodeStream;
nodeStream = Stream.of(s.getLeftNode(), s.getRightNode()).filter(n -> n != null);
return nodeStream;
}).collect(Collectors.toList());
builder.add(lineStringBuffer.toString()).add("\n");
}
return builder.build().collect(Collectors.joining());
}
public static void main(String[] args) {
Integer[] objects = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).toArray(Integer[]::new);
XbLinkedBinaryTree<Integer> build = XbLinkedBinaryTree.build(objects);
System.out.println(build.prettyToString(2));
}
}
java控制檯輸出二叉樹(二叉樹使用鏈式結構存儲)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.