Java基礎——表示式二叉樹的Java實現構建(構建+前序、中序、後序遍歷)
阿新 • • 發佈:2018-12-05
1 表示式二叉樹
1.1 定義
二叉樹:在電腦科學中,二叉樹是每個結點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。
表示式二叉樹:儲存表示式的二叉樹。
如:45+23*56/2-5(例子來源:https://www.cnblogs.com/yuxiuyan/p/5753006.html)
首先取出第一個數字45放在葉子節點,遇到“+”後將其放到分支節點,
然後將“23”、“*”、“56”、“/”、“2”依次放入,
最後放入“-”、“5”,
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);
}
}