1. 程式人生 > >Java基礎——表示式二叉樹的Java實現構建(構建+前序、中序、後序遍歷)

Java基礎——表示式二叉樹的Java實現構建(構建+前序、中序、後序遍歷)

1 表示式二叉樹

1.1 定義

二叉樹:在電腦科學中,二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。

表示式二叉樹:儲存表示式的二叉樹。

如:45+23*56/2-5(例子來源:https://www.cnblogs.com/yuxiuyan/p/5753006.html

首先取出第一個數字45放在葉子節點,遇到“+”後將其放到分支節點,

fig1.構建過程1

然後將“23”、“*”、“56”、“/”、“2”依次放入,

fig2.構建過程2

最後放入“-”、“5”,

fig3.構建過程3

 

1.2 構建步驟

  • 1.建立節點物件;
  • 2.辨析出操作符與資料,存放在相應的陣列佇列(型別為BinaryNode)中;
  • 3.取出前兩個數字和一個操作符,組成一個新的數字節點;
  • 4.重複第3步,直到操作符取完為止;
  • 5.讓根節點等於最後一個節點。

 

2 構建

1.1 節點類

節點類包括三個引數:

private String data;
private BinaryNode left;
private BinaryNode right;

方法包括:

有參構造方法:在建立時必須初始化data

public BinaryNode(String data) {
    this.data = data;
}

引數的set、get方法:

構建節點時,需要set其左右子樹;

遍歷二叉樹時,需要get其左右子樹、以及get其data。

 

1.2 二叉樹類

package com.java8.binarytree;

import java.util.ArrayList;
import java.util.Stack;

/**
 * 二叉樹類
 * 擁有屬性為root,其構建後為數的根節點
 */
public class BinaryTree {

    //根節點
    private BinaryNode root = new BinaryNode(null);
    public BinaryNode getRoot() {
        return root;
    }


    //—————————————————————————————————建立 和 輸出 1 ———————————————————————————————————————

    /**
     * 建立表示式二叉樹
     * @param str :輸入為字串
     */
    public void build(String str) {
        // numbers儲存數字和節點,operations儲存運算子號
        // binaryNode用於構建數,snum用於接受個位十位百位數字
        ArrayList<BinaryNode> numbers = new ArrayList<>();
        ArrayList<BinaryNode> operations = new ArrayList<>();
        BinaryNode binaryNode;
        String snum = "";

        //1.遍歷str,找出所有的運算子和數字,存入numbers和operations陣列佇列
        for (int i = 0; i < str.length(); i++) {
            //1.1 取出字串的各個字元
            char ch = str.charAt(i);
            //1.2 判斷為符號還是數字,若為數字,則將s+=ch(防止數字為十位百位數)
            if (ch >= '0' && ch <= '9') {
                snum += ch + "";
            }
            //1.3 若為運算子,則將s和ch分別放入numbers、operations陣列佇列
            else {
                numbers.add(new BinaryNode(snum));
                operations.add(new BinaryNode(ch + " "));
                snum = "";
            }
        }
        //1.4 將最後一位數字放入numbers陣列佇列
        numbers.add(new BinaryNode(snum));


        //2. 迴圈構建樹,直至operations佇列為空結束
        while(!operations.isEmpty()) {
            // 2.1從運算子中取出第一個作為node的資料;
            binaryNode = operations.get(0);
            operations.remove(0);
            //2.2從數字取出第一個、第二個作為左、右;
            binaryNode.setLeft(numbers.get(0));
            binaryNode.setRight(numbers.get(1));
            numbers.remove(0);
            numbers.remove(0);
            //2.3構建node,將其作為根節點root放回數字列表
            root = binaryNode;
            numbers.add(0, binaryNode);
        }
    }


    /**
     * 選擇方式遍歷輸出表達式二叉樹
     * @param i:1——先序 2——中序 3——後序
     */
    public void output(int i) {
        switch (i) {
            case 1:
                System.out.println("輸出——先序遍歷:");
                preOrder(root);
                System.out.println("");
                break;
            case 2:
                System.out.println("輸出——中序遍歷:");
                midOrder(root);
                System.out.println("");
                break;
            case 3:
                System.out.println("輸出——後序遍歷:");
                posOrder(root);
                System.out.println("");
                break;
        }

    }


    //—————————————————————————————————遍歷 3———————————————————————————————————————


    /**
     * 遞迴方法 —— 前序遍歷的規則:
     * (1)訪問根節點
     * (2)前序遍歷左子樹
     * (3)前序遍歷右子樹
     */
    public void preOrder(BinaryNode node) {
        if (node != null) {
            System.out.print(node.getData() + " ");
            preOrder(node.getLeft());
            preOrder(node.getRight());
        }
    }

    /**
     * 遞迴方法 —— 中序遍歷的規則:
     * (1)中序遍歷左子樹
     * (2)訪問根節點
     * (3)中序遍歷右子樹
     */
    public void midOrder(BinaryNode node) {
        if (node != null) {
            midOrder(node.getLeft());
            System.out.print(node.getData() + " ");
            midOrder(node.getRight());
        }
    }


    /**
     * 遞迴方法 —— 後序遍歷的規則:
     * (1)後序遍歷左子樹
     * (2)後序遍歷右子樹
     * (3)訪問根節點
     */
    public void posOrder(BinaryNode node) {
        if (node != null) {
            posOrder(node.getLeft());
            posOrder(node.getRight());
            System.out.print(node.getData() + " ");
        }
    }


    /**
     * 非遞迴方法 —— 前序遍歷的規則:
     * (1)訪問根節點
     * (2)前序遍歷左子樹
     * (3)前序遍歷右子樹
     */
    public void preOrder2() {
        BinaryNode node = root;
        Stack<BinaryNode> stack = new Stack<>();
        ArrayList<String> preList = new ArrayList<>();


        while (node != null || stack.size() != 0) {
            while (node != null) {
                stack.push(node);
                preList.add(node.getData());

                node = node.getLeft();
            }
            if (stack.size() != 0) {
                node = stack.pop();
                node = node.getRight();
            }
        }
        System.out.println("非遞迴——先序遍歷:" + preList.toString());

    }

    /**
     * 非遞迴方法 —— 中序遍歷的規則:
     * (1)中序遍歷左子樹
     * (2)訪問根節點
     * (3)中序遍歷右子樹
     */
    public void midOrder2() {
        Stack<BinaryNode> stack = new Stack<>();
        ArrayList<String> midList = new ArrayList<>();
        BinaryNode node = root;
        while (node != null || stack.size() != 0) {
            while (node != null) {
                stack.push(node);
                node = node.getLeft();
            }
            if (stack.size() != 0) {
                node = stack.pop();
                midList.add(node.getData());
                node = node.getRight();
            }
        }
        System.out.println("非遞迴——中序遍歷: " + midList.toString());
    }


    //—————————————————————————————————測試 2———————————————————————————————————————

    /**
     * 輸出檢驗函式,檢視numbers和operations是否已經存入資料
     * @param list:Node列表
     */
    public void printList(ArrayList<BinaryNode> list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i));
            System.out.print("    ");
        }
    }

    /**
     * 輸出檢驗函式,Stack是否已經存入資料
     * @param list:Node列表
     */
    public void printList(Stack<BinaryNode> list) {
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i).getData());
            System.out.print("    ");
        }
    }

}

 

3 遍歷

3.1 遍歷方式

例子:45+23*56/2-5

先序遍歷:-  /  *  +  45 23 56 2 5 

/**
 * 遞迴方法 —— 前序遍歷的規則:
 * (1)訪問根節點
 * (2)前序遍歷左子樹
 * (3)前序遍歷右子樹
 */

中序遍歷:45 +  23 *  56 /  2 -  5 

/**
 * 遞迴方法 —— 中序遍歷的規則:
 * (1)中序遍歷左子樹
 * (2)訪問根節點
 * (3)中序遍歷右子樹
 */

後序遍歷:45 23 +  56 *  2 /  5 - 

/**
 * 遞迴方法 —— 後序遍歷的規則:
 * (1)後序遍歷左子樹
 * (2)後序遍歷右子樹
 * (3)訪問根節點
 */

 

程式碼:

2.2中的BinaryTree中的第二部分

 

4 測試類

package com.java8.binarytree;

public class Manage {
    public static void main(String[] args) {
        //建立binaryTree物件,其初始包含data為null的root節點
        BinaryTree binaryTree = new BinaryTree();
        //build二叉樹時,需要輸入表示式的String
        binaryTree.build("45+23*56/2-5");
        //檢視是否構建完成,獲取現在的root節點
        System.out.println("二叉樹的root為: "+binaryTree.getRoot().getData());
        binaryTree.output(1);
        binaryTree.output(2);
        binaryTree.output(3);
    }
}

 

fig4.測試結果