java控制檯輸出二叉樹(二叉樹使用數組結構存儲)

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);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章