二分搜索樹是有順序的樹,某節點T的左子樹都小於T節點,T的右子樹均大於T節點的值。 實現的關鍵代碼爲add操做,用遞歸很容易實現。java
package tree;
/* * @Param * */
public class BST<E extends Comparable<E>> {
private class Node {
public E e;
public Node left, right;
public Node(E e) {
this.e = e;
left = null;
right = null;
}
}
private Node root;
private int size;
public BST() {
root = null;
size = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
/* * 第一種add代碼相對複雜,邏輯更清晰 * */
/* public void add(E e){ if (root==null){ root=new Node(e);size++; }else add(root,e); } private void add(Node node, E e) { //終止條件: -- 多個終止條件---終止條件直接返回 if (node.e.equals(e)) return; else if (node.e.compareTo(e)<0 && node.right==null){ node.right=new Node(e);size++; return; } else if (node.e.compareTo(e)>0 && node.left==null){ node.left=new Node(e);size++; return; } //規模減少 if (node.e.compareTo(e)<0) add(node.right,e); else add(node.left,e); }*/
public void add(E e) {
root = add(root, e);
}
private Node add(Node node, E e) {
//終止條件
if (node == null) {
size++;
return new Node(e);
}
//規模減少,這裏邏輯容易出錯。
if (e.compareTo(node.e) > 0)
node.right = add(node.right, e);
else if (e.compareTo(node.e) < 0)
node.left = add(node.left, e);
return node;
}
}
複製代碼
public boolean contains(E e){
return contains(root,e);
}
private boolean contains(Node node, E e) {
//2.終止條件
if (node.e.compareTo(e)==0)
return true;
else if (node==null)
return false;
//1.規模減小1
if (e.compareTo(node.e)>0)
return contains(node.right,e);
else //if (e.compareTo(node.e)<0)
return contains(node.left,e);
}
複製代碼
//前序遍歷操做,遞歸方法
public void preOder(){
preOder(root);
}
public void preOder(Node node){
//2.終止條件
if (node==null)
return;
/* * 1.規模縮小。 * 訪問該節點---》訪問該節點的左子樹、和右子樹。 * */
System.out.println(node.e);
preOder(node.left);
preOder(node.right);
}
/* * 簡單寫法 * 推薦第一種遞歸寫法,邏輯比較清晰。 * * if(node!=null){ System.out.println(node.e); preOder(node.left); preOder(node.right); * } * * */
複製代碼
須要記錄每個節點的訪問狀態,若是不能使用遞歸,就要藉助棧來記錄。node
//前序遍歷,非遞歸
//非遞歸方法,須要藉助棧來記錄訪問順序
/* * 出棧的同時,入棧兩個子節點。 * */
public void preOderNR() {
Stack<Node> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
Node cur = stack.pop();
System.out.println(cur.e);
if (cur.right != null)
stack.push(cur.right);
if (cur.left != null)
stack.push(cur.left);
}
}
複製代碼
public E minimum(){
if (size==0)
throw new IllegalArgumentException("empty");
return minimum(root).e;
}
private Node minimum(Node node) {
if (node.left == null) {
return node;
}
return minimum(node.left);
}
public E max(){
if (size==0)
throw new IllegalArgumentException("empty");
return max(root).e;
}
private Node max(Node node) {
if (node.right == null) {
return node;
}
return max(node.right);
}
public E removeMax(){
E e=max();
//recurse removeMax(root)
removeMax(root);
return e;
}
private Node removeMax(Node node) {
//end condition
if (node.right == null) {
Node leftN = node.left;
node.left=null;
size--;
return leftN;
}
//-1
node.right=removeMax(node.right);
return node;
}
public E removeMin(){
E e=minimum();
removeMin(root);
return e; }
private Node removeMin(Node node) {
if (node.left == null) {
Node right = node.right;
node.right=null;
size--;
return right;
}
node.left=removeMin(node.left);
return node;
}
public void remove(E e){
remove(root,e);
}
private Node remove(Node node, E e) {
if (node == null) {
return null;
}
if (e.compareTo(node.e)<0){
node.left=remove(node.left,e);
return node;
}
else if (e.compareTo(node.e)>0){
node.right=remove(node.right,e);
return node;
}
else //== keyPoint
{
//分三種狀況,前兩種比較簡單
if (node.left==null){
Node rightNode = node.right;
node.right=null;
size--;
return rightNode;
}
if (node.right==null){
Node left = node.left;
node.left=null;
size--;
return left;
}
/* 核心代碼!!! //hib deltion 左右都不空時,找到比該節點大的最小節點,取代該節點。 */
Node successor=minimum(node.right);
successor.right=removeMin(node.right);
successor.left=node.left;
//刪除當前節點。沒用了
node.left=node.right=null;
return successor;
}
}
複製代碼