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控制檯輸出二叉樹(二叉樹使用數組結構存儲)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.