20192314 2020—2021—1 《資料結構與面向物件程式設計》實驗八 樹
1.參考教材PP16.1,完成鏈樹LinkedBinaryTree的實現(getRight,contains,toString,preorder,postorder)
用JUnit或自己編寫驅動類對自己實現的LinkedBinaryTree進行測試,提交測試程式碼執行截圖,要全屏,包含自己的學號資訊
課下把程式碼推送到程式碼託管平臺
程式程式碼
LinkedBinaryTree
import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; public class LinkedBinaryTree<T> implements Iterable<T>, BinaryTreeADT<T> { protected BinaryTreeNode<T> root;//設定根結點 protected int modCount; protected LinkedBinaryTree<T> left,right; public LinkedBinaryTree() { root = null; } public LinkedBinaryTree(T element) { root = new BinaryTreeNode<T>(element); } public LinkedBinaryTree(T element, LinkedBinaryTree<T> left, LinkedBinaryTree<T> right) { root = new BinaryTreeNode<T>(element); root.setLeft(left.root); root.setRight(right.root); this.left = left; this.right=right; } //呼叫binarylinktree public BinaryTreeNode<T> getRootNode() throws EmptyCollectionException { if (isEmpty()) { throw new EmptyCollectionException("BinaryTreeNode "); } return root; } public LinkedBinaryTree<T> getLeft() { return left; } public LinkedBinaryTree<T> getRight() { return right; } public int getHeight() { return height(root); } //樹的深度計算 private int height(BinaryTreeNode<T> node) { if(node==null){ return 0; } else { int leftTreeHeight = height(node.getLeft()); int rightTreeHeight= height(node.getRight()); return leftTreeHeight>rightTreeHeight ? (leftTreeHeight+1):(rightTreeHeight+1); } } //獲取樹根的元素 @Override public T getRootElement() throws EmptyCollectionException { if (root.getElement().equals(null)) { throw new EmptyCollectionException("BinaryTreeNode "); } return root.getElement(); } @Override public boolean isEmpty() { return (root == null); } @Override public int size() { int size = 0; if(root.getLeft()!=null){ size+=1; } if(root.getRight()!=null){ size+=1; } return size; } //刪除右側結點 public String removeRightSubtree() throws EmptyCollectionException { if (root == null) throw new EmptyCollectionException("tree is empty"); BinaryTreeNode cur = root; while (cur.getLeft() != null){ cur.setRight(null); cur = cur.left; } return super.toString(); } //刪除全部元素 public void removeAllElements() throws EmptyCollectionException { if (root == null) throw new EmptyCollectionException("tree is empty"); root = null; } //boolean元素查詢 @Override public boolean contains(T targetElement) { if(targetElement == find(targetElement)) return true; else return false; } @Override // 獲取當前元素 public T find(T targetElement) { BinaryTreeNode<T> current = findAgain(targetElement, root); if (current == null) try { throw new ElementNotFoundException("LinkedBinaryTree"); } catch (ElementNotFoundException e) { e.printStackTrace(); } return (current.getElement()); } private BinaryTreeNode<T> findAgain(T targetElement, BinaryTreeNode<T> next) { if (next == null) return null; if (next.getElement().equals(targetElement)) return next; // 運用遞迴進行子樹的查詢 BinaryTreeNode<T> temp = findAgain(targetElement, next.getLeft()); if (temp == null) temp = findAgain(targetElement, next.getRight()); return temp; } //中序輸出 @Override public Iterator<T> iteratorInOrder() { ArrayListUnordered<T> tempList = new ArrayListUnordered<T>(); inOrder(root, tempList); return new TreeIterator(tempList.iterator()); } //前序的輸出 public void toPreString(){ preOrder(root); } private void preOrder(BinaryTreeNode root){ if(null!= root){ System.out.print(root.getElement() + "\t"); preOrder(root.getLeft()); preOrder(root.getRight()); } } //後序輸出 public void toPostString(){ postOrder(root); } private void postOrder(BinaryTreeNode root) { if (null != root) { postOrder(root.getLeft()); postOrder(root.getRight()); System.out.print(root.getElement() + "\t"); } } protected void inOrder(BinaryTreeNode<T> node, ArrayListUnordered<T> tempList) { if (node != null) { inOrder(node.getLeft(), tempList); tempList.addToRear(node.getElement()); inOrder(node.getRight(), tempList); } } //運用遞迴方法的前序查詢 @Override public Iterator<T> iteratorPreOrder() { ArrayListUnordered<T> tempList = new ArrayListUnordered<T>(); preOrder(root, tempList); return new TreeIterator(tempList.iterator()); } private void preOrder(BinaryTreeNode<T> node, ArrayListUnordered<T> tempList) { if (node != null) { tempList.addToRear(node.getElement()); inOrder(node.getLeft(), tempList); inOrder(node.getRight(), tempList); } } //運用迭代方法的後序查詢 @Override public Iterator<T> iteratorPostOrder() { ArrayListUnordered<T> tempList = new ArrayListUnordered<T>(); postOrder(root, tempList); return new TreeIterator(tempList.iterator()); } private void postOrder(BinaryTreeNode<T> node, ArrayListUnordered<T> tempList) { if (node != null) { tempList.addToRear(node.getElement()); inOrder(node.getLeft(), tempList); inOrder(node.getRight(), tempList); } } //遞迴方法的層序遍歷 @Override public Iterator<T> iteratorLevelOrder() { //遞迴方法的層序遍歷 ArrayListUnordered<BinaryTreeNode<T>> nodes = new ArrayListUnordered<BinaryTreeNode<T>>(); ArrayListUnordered<T> tempList = new ArrayListUnordered<T>(); BinaryTreeNode<T> current; nodes.addToRear(root); while (!nodes.isEmpty()) { current = nodes.removeFirst(); if (current != null) { tempList.addToRear(current.getElement()); System.out.println(current.element); if (current.getLeft() != null) nodes.addToRear(current.getLeft()); System.out.println(current.left); if (current.getRight() != null) nodes.addToRear(current.getRight()); System.out.println(current.right); } else tempList.addToRear(null); } return new TreeIterator(tempList.iterator()); } //層序輸出 public void toLevelString1(){ if(root == null) return; int height = getHeight(); for(int i = 1; i <= height; i++){ levelOrder(root,i); } } private void levelOrder(BinaryTreeNode root,int level){ if(root == null || level < 1){ return; } if(level == 1){ System.out.print(root.getElement() + "\n"); return; } levelOrder(root.getLeft(),level - 1); levelOrder(root.getRight(),level - 1); } //輸出樹的方法!!! @Override public Iterator<T> iterator() { return iteratorInOrder(); } public String toString() { UnorderedListADT<BinaryTreeNode<T>> nodes = new ArrayListUnordered<BinaryTreeNode<T>>(); UnorderedListADT<Integer> levelList = new ArrayListUnordered<Integer>(); BinaryTreeNode<T> current; String result = ""; int Depth = this.getHeight();//高度和深度計算 int possibleNodes = (int) Math.pow(2, Depth + 1); int countNodes = 0; nodes.addToRear(root); Integer curLevel = 0; Integer preLevel = -1; levelList.addToRear(curLevel); while (countNodes < possibleNodes) { countNodes = countNodes + 1; current = nodes.removeFirst(); curLevel = levelList.removeFirst(); if (curLevel > preLevel) { result = result+ "\n\n"; preLevel = curLevel; for (int j = 0; j < ((Math.pow(2, (Depth - curLevel))) - 1); j++) result = result + " "; } else { for (int i = 0; i < (Math.pow(2, (Depth - curLevel + 1)) - 1); i++) { result = result + " "; } } if (current != null) { result = result + (current.getElement()).toString(); nodes.addToRear(current.getLeft()); levelList.addToRear(curLevel + 1); nodes.addToRear(current.getRight()); levelList.addToRear(curLevel + 1); } else { nodes.addToRear(null); levelList.addToRear(curLevel + 1); result = result + " "; } } return result; } //設定右結點 public void setRight(LinkedBinaryTree<T> right) { this.right = right; } private class TreeIterator implements Iterator<T> { private int expectedModCount; private Iterator<T> iter; //迭代 public TreeIterator(Iterator<T> iter) { this.iter = iter; expectedModCount = modCount; } public boolean hasNext() throws ConcurrentModificationException { if (!(modCount == expectedModCount)) throw new ConcurrentModificationException(); return (iter.hasNext()); } public T next() throws NoSuchElementException { if (hasNext()) return (iter.next()); else throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }
}
BinaryTreeADT
import java.util.Iterator; public interface BinaryTreeADT<T> { public T getRootElement() throws EmptyCollectionException ; public boolean isEmpty(); public int size(); public boolean contains(T targetElement); public T find(T targetElement); public String toString(); public Iterator<T> iterator(); public Iterator<T> iteratorInOrder(); public Iterator<T> iteratorPreOrder(); public Iterator<T> iteratorPostOrder(); public Iterator<T> iteratorLevelOrder();
}
LinkedBinaryTreeTest
import java.util.Iterator; public class LinkedBinaryTreeTest { public static void main(String[] args) { LinkedBinaryTree num1 = new LinkedBinaryTree("2"); LinkedBinaryTree num2 = new LinkedBinaryTree("0"); LinkedBinaryTree num3 = new LinkedBinaryTree("1"); LinkedBinaryTree num4 = new LinkedBinaryTree("8",num1,num3); LinkedBinaryTree num5 = new LinkedBinaryTree("3",num2,num4); LinkedBinaryTree num6 = new LinkedBinaryTree("0",num4,num5); Iterator it; System.out.println("right of 8: "); System.out.println(num4.getRight()); System.out.println("Contains 2? "); System.out.println(num1.contains("2")); System.out.println("PreOrder: "); num6 .toPreString() ; System.out.println(); System.out.println("PostOrder: "); num6 .toPostString() ; System.out.println(num6.toString()); }
}
EmptyCollectionException
public class EmptyCollectionException extends RuntimeException
{
public EmptyCollectionException (String collection)
{
super ("The " + collection + " is empty.");
}
}
UnorderedListADT
public interface UnorderedListADT
{
public void addToFront(T element);
public void addToRear(T element);
public void addAfter(T element, T target);
}
ElementNotFoundException
public class ElementNotFoundException extends RuntimeException
{
public ElementNotFoundException (String collection)
{
super ("The target element is not in this " + collection);
}
}
ListADT
import java.util.Iterator;
public interface ListADT
{
public T removeFirst();
public T removeLast();
public T remove(T element);
public T first();
public T last();
public boolean contains(T target);
public boolean isEmpty();
public int size();
public Iterator
public String toString();
}
ArrayIterator
import java.util.ArrayList;
//使用iterator遍歷集合的同時對集合進行修改就會出現java.util.ConcurrentModificationException異常
import java.util.ConcurrentModificationException;
import java.util.Iterator;
public class ArrayIterator<T> extends ArrayList<T> implements Iterator<T> {
int iteratorModCount;
int current;
public ArrayIterator()
{
iteratorModCount = modCount;
current = 0;
}
public boolean hasNext() throws ConcurrentModificationException
{
return super.iterator().hasNext();
}
public T next() throws ConcurrentModificationException
{
return super.iterator().next();
}
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
}
ArrayListUnordered
public class ArrayListUnordered<T> extends ArrayList<T> implements UnorderedListADT<T> {
@Override
public void addToFront(T element) {
if (size() == list.length)
expandCapacity();
for (int i=rear;i > 0; i--)
list[i] = list[i - 1];
list[0] = element;
rear++;
modCount++;
}
@Override
public void addToRear(T element) {
if (size() == list.length)
expandCapacity();
list[rear] = element;
rear++;
modCount++;
}
@Override
public void addAfter(T element, T target) {
if (size() == list.length)
expandCapacity();
int scan = 0;
//find the insertion point
while (scan < rear && !target.equals(list[scan]))
scan++;
if (scan == rear)
try {
throw new ElementNotFoundException("UnorderedList");
} catch (ElementNotFoundException e) {
e.printStackTrace();
}
scan++;
for (int shilt = rear; shilt > scan; shilt--)
list[shilt] = list[shilt - 1];
list[scan] = element;
rear++;
modCount++;
}
}
ArrayList
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
public abstract class ArrayList<T> implements ListADT<T>, Iterable<T>
{
private final static int DEFAULT_CAPACITY = 100;
private final static int NOT_FOUND = -1;
protected int rear;
protected T[] list;
protected int modCount;
public ArrayList()
{
this(DEFAULT_CAPACITY);
}
public ArrayList(int initialCapacity)
{
rear = 0;
list = (T[])(new Object[initialCapacity]);
modCount = 0;
}
protected void expandCapacity(){
list = Arrays.copyOf(list,list.length*2);
}
@Override
public T removeLast() throws EmptyCollectionException {
T result = list[rear-1];
list[rear]=null;
rear --;
return result;
}
@Override
public T removeFirst() throws EmptyCollectionException {
T result =list[0];
rear--;
for(int i = 0; i< rear; i++){
list[i] = list[i + 1];
}
list[rear] = null;
return result;
}
@Override
public T remove(T element)
{
T result;
int index = find(element);
if (index == NOT_FOUND)
try {
throw new ElementNotFoundException("ArrayList");
} catch (ElementNotFoundException e) {
e.printStackTrace();
}
result = list[index];
rear--;
for (int scan=index; scan < rear; scan++)
list[scan] = list[scan+1];
list[rear] = null;
modCount++;
return result;
}
@Override
public T first() throws EmptyCollectionException
{
T result = list[0];
return result;
}
@Override
public T last() throws EmptyCollectionException
{
T result = list[rear-1];
return result;
}
@Override
public int size(){
return rear;
}
@Override
public boolean contains(T target)
{
return (find(target) != NOT_FOUND);
}
private int find(T target)
{
int scan = 0;
int result = NOT_FOUND;
if (!isEmpty()) {
while (result == NOT_FOUND && scan < rear)
if (target.equals(list[scan]))
result = scan;
else
scan++;
}
return result;
}
@Override
public boolean isEmpty(){
if(size() == 0){
return true;
}else
return false;
}
@Override
public String toString(){
String string = "";
for (int i = 0;i < rear;i++){
string += list[i] + " ";
}
return string;
}
@Override
public Iterator<T> iterator(){
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<T>
{
int iteratorModCount;
int current;
public ArrayListIterator()
{
iteratorModCount = modCount;
current = 0;
}
@Override
public boolean hasNext() throws ConcurrentModificationException
{
if (iteratorModCount != modCount)
throw new ConcurrentModificationException();
return (current < rear);
}
@Override
public T next() throws ConcurrentModificationException
{
if (!hasNext())
throw new NoSuchElementException();
current++;
return list[current - 1];
}
@Override
public void remove() throws UnsupportedOperationException
{
throw new UnsupportedOperationException();
}
}
}
BinaryTreeNode
public class BinaryTreeNode<T> {
protected T element;
protected BinaryTreeNode<T> left;
protected BinaryTreeNode<T> right;
public BinaryTreeNode(T obj) {
this.element = obj;
this.left = null;
this.right = null;
}
///合併構建宣告
public BinaryTreeNode(T obj, LinkedBinaryTree<T> left,
LinkedBinaryTree<T> right)throws EmptyCollectionException {
element = obj;
if (left == null)
this.left = null;
else
this.left = left.getRootNode();
if (right == null)
this.right = null;
else
this.right = right.getRootNode();
}
public int numChildren() {
int children = 0;
if (left != null)
children = 1 + left.numChildren();
if (right != null)
children = children + 1 + right.numChildren();
return children;
}
public T getElement() {
return element;
}
public BinaryTreeNode<T> getRight() {
return right;
}
public void setRight(BinaryTreeNode<T> node) {
right = node;
}
public BinaryTreeNode<T> getLeft() {
return left;
}
public void setLeft(BinaryTreeNode<T> node) {
left = node;
}
public boolean judge(){
if(right == null && left == null)
//葉結點的左側和右側都沒有結點
return true;
else
return false;
}
}
執行截圖
基於LinkedBinaryTree,實現基於(中序,先序)序列構造唯一一棵二㕚樹的功能,比如給出中序HDIBEMJNAFCKGL和###後序ABDHIEJMNCFGKL,構造出附圖中的樹
用JUnit或自己編寫驅動類對自己實現的功能進行測試,提交測試程式碼執行截圖,要全屏,包含自己的學號資訊
課下把程式碼推送到程式碼託管平臺
程式程式碼
import java.util.Scanner;
import java.util.StringTokenizer;
public class CreateTree {
public LinkedBinaryTree<String> CreatTree(String inorder[],String preorder[]){
LinkedBinaryTree<String> binaryTree = null;
if(inorder.length == preorder.length && inorder.length != 0 && preorder.length != 0){
int n = 0;
//根據前序遍歷第一個root 進行中序遍歷
while (!inorder[n].equals(preorder[0])) {
n++;
}
//根據前序遍歷第一個root 進行中序遍歷
//左子樹的陣列輸入
String[] preLeft = new String[n];
String[] inLeft = new String[n];
//右子樹的陣列輸入
String[] preRight = new String[preorder.length - n - 1];
String[] inRight = new String[inorder.length - n - 1];
for (int t = 0; t < inorder.length; t++) {
if (t < n) {
preLeft[t] = preorder[t + 1];//左子樹生成
inLeft[t] = inorder[t];//左子樹生成
}
if (t > n) {
preRight[t - n - 1] = preorder[t];//右子樹生成
inRight[t - n - 1] = inorder[t];//右子樹生成
}
if(t == n){//
continue;
}
}
/* //重新生成樹
LinkedBinaryTree<String> left = CreatTree(inLeft, preLeft);
LinkedBinaryTree<String> right = CreatTree(inRight, preRight);
binaryTree = new LinkedBinaryTree<String>(preorder[0], left, right);//樹的輸出
// System.out.println(binaryTree.toString());*/
LinkedBinaryTree<String> left = CreatTree(inLeft, preLeft);
LinkedBinaryTree<String> right = CreatTree(inRight, preRight);
binaryTree = new LinkedBinaryTree<String>(preorder[0], left, right);//樹的輸出
// System.out.println(binaryTree.toString());
}else
//若不滿足以下條件則無法構成一棵樹。無法生成樹
{
binaryTree = new LinkedBinaryTree<>();
}
return binaryTree;
}
public static void main(String[] args)
{
String a,b;
int i = 0,j = 0;
Scanner scanner = new Scanner(System.in);
System.out.println("Input the PreOrder:");
a = scanner.nextLine();
System.out.println("Input the PostOrder:");
b = scanner.nextLine();
//分別用" "分割,取出每個字元
StringTokenizer str1 = new StringTokenizer(a, " ");
StringTokenizer str2= new StringTokenizer(b, " ");
//陣列
String[] string1 = new String[str1.countTokens()];
String[] string2 = new String[str2.countTokens()];
//放入陣列
while (str1.hasMoreTokens())
{
string1[i] = str1.nextToken();
i++;
}
while (str2.hasMoreTokens())
{
string2[j] = str2.nextToken();e(string2,string1);
System.out.println("The Tree is:");
j++;
}
//中序輸出
//前序輸出
CreateTree ct = new CreateTree();
LinkedBinaryTree<String> binaryTree = ct.CreatTre
System.out.println();
System.out.println(binaryTree.toString());
}
}
執行截圖
自己設計並實現一顆決策樹
提交測試程式碼執行截圖,要全屏,包含自己的學號資訊
課下把程式碼推送到程式碼託管平臺
程式程式碼
import java.util.Scanner;
public class PsychologicalTest
{
private LinkedBinaryTree
public PsychologicalTest()
{
String e1 = "你玩CSGO嗎 ?";
String e2 = "你玩崩壞三嗎 ?";
String e3 = "你經常打競技排位嗎 ?";
String e4 = "你有物件嗎 ?";
String e5 = "你氪金了嗎 ?";
String e6 = "你喜歡打倉庫圖嗎 ?";
String e7 = "你的段位達到了大地球嗎 ?";
String e8 = "同道單身狗";
String e9 = "咱倆無話可聊";
String e10 = "窮鬼";
String e11 = "大戶人家";
String e12 = "祝你早日登上大地球";
String e13 = "nt";
String e14 = "廢物";
String e15 ="精神小夥";
LinkedBinaryTree<String> n2, n3, n4, n5, n6, n7, n8, n9,
n10, n11, n12, n13,n14,n15;
n8 = new LinkedBinaryTree<String>(e8);
n9 = new LinkedBinaryTree<String>(e9);
n4 = new LinkedBinaryTree<String>(e4, n8, n9);
n10 = new LinkedBinaryTree<String>(e10);
n11 = new LinkedBinaryTree<String>(e11);
n5 = new LinkedBinaryTree<String>(e5, n10, n11);
n12 = new LinkedBinaryTree<String>(e12);
n13 = new LinkedBinaryTree<String>(e13);
n6 = new LinkedBinaryTree<String>(e6, n12, n13);
n14 = new LinkedBinaryTree<String>(e14);
n15 = new LinkedBinaryTree<String>(e15);
n7 = new LinkedBinaryTree<String>(e7,n14,n15);
n2 = new LinkedBinaryTree<String>(e2, n4, n5);
n3 = new LinkedBinaryTree<String>(e3, n6, n7);
tree = new LinkedBinaryTree<String>(e1, n2, n3);
}
public void start()
{
Scanner scan = new Scanner(System.in);
LinkedBinaryTree<String> current = tree;
System.out.println ("讓我們聊一聊");
while (current.size() > 1)
{
System.out.println (current.getRootElement());
if (scan.nextLine().equalsIgnoreCase("N"))
current = current.getLeft();
else
current = current.getRight();
}
System.out.println (current.getRootElement());
}
public static void main(String[] args){
PsychologicalTest test = new PsychologicalTest();
test.start();
}
}
執行截圖
輸入中綴表示式,使用樹將中綴表示式轉換為字尾表示式,並輸出字尾表示式和計算結果(如果沒有用樹,正常評分。###如果用到了樹,即使有小的問題,也酌情給滿分)
提交測試程式碼執行截圖,要全屏,包含自己的學號資訊
程式程式碼
FixTest
import java.util.Scanner;
public class FixTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("請輸入表示式:");
String s = scan.nextLine();
Fix fix = new Fix();
System.out.println("字尾表示式為:\n"+Fix.getrp(s));
System.out.println("計算結果為:\n"+fix.calrp(Fix.getrp(s)));
}
}
Fix
import java.util.Stack;
public class Fix {
static Stack<Character> op = new Stack<>();
public static Float getv(char op, Float f1, Float f2) {
if (op == '+') return f2 + f1;
else if (op == '-') return f2 - f1;
else if (op == '*') return f2 * f1;
else if (op == '/') return f2 / f1;
else return Float.valueOf(-0);
}
public static float calrp(String rp) {
Stack<Float> v = new Stack<>();
char[] arr = rp.toCharArray();
int len = arr.length;
for (int i = 0; i < len; i++) {
Character ch = arr[i];
if (ch >= '0' && ch <= '9') v.push(Float.valueOf(ch - '0'));
else v.push(getv(ch, v.pop(), v.pop()));
}
return v.pop();
}
public static String getrp(String s) {
char[] arr = s.toCharArray();
int len = arr.length;
String out = "";
for (int i = 0; i < len; i++) {
char ch = arr[i];
if (ch == ' ') continue;
if (ch >= '0' && ch <= '9') {
out += ch;
continue;
}
if (ch == '(')
op.push(ch);
if (ch == '+' || ch == '-') {
while (!op.empty() && (op.peek() != '('))
out += op.pop();
op.push(ch);
continue;
}
if (ch == '*' || ch == '/') {
while (!op.empty() && (op.peek() == '*' || op.peek() == '/'))
out += op.pop();
op.push(ch);
continue;
}
if (ch == ')') {
while (!op.empty() && op.peek() != '(')
out += op.pop();
op.pop();
continue;
}
}
while (!op.empty()) out += op.pop();
return out;
}
}
執行截圖
實驗心得
問題1:子樹無法通過連結串列方式與根節點相連線。
問題1解決方案:
將節點的定義方式更改,從下往上定義節點,在根節點處定義時直接將左右兩個子樹的根節點連線在根節點上。
問題2:在寫決策樹時,一開始沒有仔細學習,就看了一下老師的決策樹程式碼和簡單的聽了聽,結果寫的時候根本寫不出來
問題2解決方案:亂寫了幾次實驗後,我意識到自己就這麼寫確實寫不出來,於是我重新看了看有關決策樹的部落格,並請教了同學,才實現了決策樹。