[JAVA]二元搜尋樹/ 排序二元樹(Binary Search Tree - BST)實現新刪修查

int[] array = {7,3,10,5,9,12,6,8,15,13,28};
package utitled;

public class BinarySearchTreeDemo {
  public static void main(String[] args) {
    int[] array = {7,3,10,5,9,12,6,8,15,13,28};
    BinarySearchTree binarySearchTree = new BinarySearchTree();
    for (int i = 0; i < array.length; i++) {
      binarySearchTree.insertNode(array[i]);
    }

    System.out.println("binarySearchTree.getRoot() = " + binarySearchTree.getRoot());
    // 中序遍歷可以得到升序的陣列
    binarySearchTree.inOrder();
    binarySearchTree.deleteNode(28);
    binarySearchTree.deleteNode(6);
    binarySearchTree.deleteNode(8);
    binarySearchTree.deleteNode(3);
    binarySearchTree.deleteNode(10);
    binarySearchTree.deleteNode(5);
    binarySearchTree.deleteNode(9);
    binarySearchTree.deleteNode(12);
    binarySearchTree.deleteNode(15);
    binarySearchTree.deleteNode(13);
    System.out.println("刪除後的中序遍歷:=====================");
    binarySearchTree.inOrder();
  }
}

class BinarySearchTree {
  private Node root;

  public Node getRoot() {
    return root;
  }

  public void insertNode(int no) {
    if (root != null) {
      root.insertNode(no);
    } else {
      root = new Node(no);
    }
  }

  public void deleteNode(int no) {
    if (root != null) {
      root.deleteNode(no);
    }
  }

  public void inOrder() {
    if (root != null) {
      root.inOrder();
    }
  }
}


class Node {
  private int no;
  private Node left;
  private Node right;
  private Node parent;

  public Node(int no) {
    this.no = no;
  }

  public int getNo() {
    return no;
  }

  public void setNo(int no) {
    this.no = no;
  }

  public Node getLeft() {
    return left;
  }

  public void setLeft(Node left) {
    this.left = left;
  }

  public Node getRight() {
    return right;
  }

  public void setRight(Node right) {
    this.right = right;
  }

  public Node getParent() {
    return parent;
  }

  public void setParent(Node parent) {
    this.parent = parent;
  }

  @Override
  public String toString() {
    final StringBuilder sb = new StringBuilder("Node{");
    sb.append("no=").append(no);
    sb.append('}');
    return sb.toString();
  }


  /**
   * 查找:找到目標結點與紀錄父結點
   * 二叉排序樹的查找是指在二叉排序樹中查找到對應的值,如在上述的二叉排序樹中查找“49”,其具體過程為:
   *
   * 與根結點的值相比:49<52,查找其左子樹
   * 49<58,查找其左子樹
   * 49>47,查找其右子樹
   * 49<51,查找其左子樹
   * 49=49,查找成功
   * @param current
   * @param no
   * @return
   */
  public Node searchTarget(Node current, int no) {
    if (current == null) {
      // 找不到目標結點
      return null;
    }
    if (no == current.getNo()) {
      // 找到目標結點
      return current;
    } else if (no < current.getNo()) {
      // 紀錄父結點
      parent = current;
      // 查找左子樹
      return searchTarget(current.getLeft(), no);
    } else {
      parent = current;
      // 查找右子樹
      return searchTarget(current.getRight(), no);
    }
  }

  /**
   * 插入
   * 對於插入操作,主要分為兩種情況:
   *
   * 若二叉排序樹中存在該值,則不做任何操作
   * 若二叉排序樹中不存在該值,則插入
   * 插入的具體操作是判斷與二叉排序樹中節點的值,若小於當前節點的值,則選擇左子樹插入,若大於當前節點的值,則選擇右子樹插入;對於左右子樹,進行同樣的操作。
   * @param no
   */
  public void insertNode(int no) {
    Node current = this;
    parent = current;
    Node temp = null;

    if (searchTarget(current, no) == null || searchTarget(current, no).getNo() != no) {
      // 查找樹中並不存在no
      temp = new Node(no);

      if (current == null) {
        // 樹為空
        current = temp;
      } else {
        if (no < parent.getNo()) {
          // 插入左子樹
          parent.setLeft(temp);
        } else {
          // 插入右子樹
          parent.setRight(temp);
        }
      }
    }
  }

  /**
   * 首先,通過查找二叉排序樹中是否存在節點,若存在,主要分為如下的三種刪除情況
   * 1. 節點既無左子樹,又無右子樹:設置父節點指向該節點的指針為空,直接刪除該節點
   * 2. 刪除的節點只包含左子樹或者只包含右子樹:刪除該節點,以其左子樹或者右子樹代替該節點
   * 3. 刪除的節點既包含左子樹,又包含右子樹:找到待刪除的節點,選擇其左子樹中的最大的節點或者其右子樹中最小的節點,替代待刪除的結點
   * @param no
   */
  public void deleteNode(int no) {
    int side = 0;
    // 判斷樹中是否存在no
    // 將parent指向待刪除結點的父結點
    Node current = this;
    parent = current;

    if (searchTarget(current, no) != null && searchTarget(current, no).getNo() == no) {
      // 樹中存在該結點
      // 開始刪除
      Node temp = null; // 指向待刪除的結點
      if (no < parent.getNo()) {
        temp = parent.getLeft();
        side = 0;
      } else if (no > parent.getNo()) {
        temp = parent.getRight();
        side = 1;
      }

      // ===========================================
      // 葉子結點,直接刪除
      if (temp.getLeft() == null && temp.getRight() == null) {
        if (no < parent.getNo()) {
          parent.setLeft(null);
        } else {
          parent.setRight(null);
        }
      } else if ((temp.getLeft() == null && temp.getRight() != null) || (temp.getLeft() != null && temp.getRight() == null)) {
        // 只有左子樹或只有右子樹
        Node child = (temp.getLeft() == null ? temp.getRight() : temp.getLeft()); // child指向不為空的子樹
        if (no < parent.getNo()) {
          parent.setLeft(child);
        } else {
          parent.setRight(child);
        }
      } else {
        // 既有左子樹又有右子樹
        Node childParent = temp.getLeft();
        // 這裡選擇左子樹最大的結點作為父結點
        // 判斷child的右子樹是否為空
        if (childParent.getRight() == null) {
          if (side == 0) {
            parent.setLeft(childParent);
          } else {
            parent.setRight(childParent);
          }
          childParent.setRight(temp.getRight());
        } else {
          Node maxNodeAtLeft = childParent;
          // 尋找右子樹
          while (maxNodeAtLeft.getRight() != null) {
            maxNodeAtLeft = maxNodeAtLeft.getRight();
          }
          // 此時maxNodeAtLeft不可能存在右子樹
          if (maxNodeAtLeft.getLeft() != null) {
            // maxNodeAtLeft存在左子樹
            childParent.setRight(maxNodeAtLeft.getLeft());
          }
          parent.setLeft(maxNodeAtLeft);
          maxNodeAtLeft.setLeft(childParent);
          maxNodeAtLeft.setRight(temp.getRight());
        }
      }
      // 將待刪除結點設null
      temp = null;
    }
  }


  /**
   * 中序遍歷
   */
  public void inOrder() {
    if (this.left != null) {
      this.left.inOrder();
    }
    System.out.println("this = " + this);
    if (this.right != null) {
      this.right.inOrder();
    }
  }

}

如有敘述錯誤,還請不吝嗇留言指教,thanks!